python-delphi-lsp 3.6.0__cp310-abi3-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. delphi_lsp/__init__.py +184 -0
  2. delphi_lsp/_version.py +1 -0
  3. delphi_lsp/agent_cache.py +1574 -0
  4. delphi_lsp/agent_cli.py +902 -0
  5. delphi_lsp/agent_context.py +3907 -0
  6. delphi_lsp/agent_cpg.py +349 -0
  7. delphi_lsp/agent_cpg_builder.py +666 -0
  8. delphi_lsp/agent_layers.py +1410 -0
  9. delphi_lsp/agent_metrics.py +526 -0
  10. delphi_lsp/agent_protocol.py +445 -0
  11. delphi_lsp/agent_relations.py +1881 -0
  12. delphi_lsp/agent_templates.py +614 -0
  13. delphi_lsp/agent_wiki.py +2853 -0
  14. delphi_lsp/agent_workspace.py +860 -0
  15. delphi_lsp/ast_serialize.py +126 -0
  16. delphi_lsp/binary.py +250 -0
  17. delphi_lsp/comment_builder.py +28 -0
  18. delphi_lsp/consts.py +345 -0
  19. delphi_lsp/delphi_lsp_native.pyd +0 -0
  20. delphi_lsp/delphiast_lexer.py +399 -0
  21. delphi_lsp/delphiast_parser.py +2189 -0
  22. delphi_lsp/delphiast_tokens.py +41 -0
  23. delphi_lsp/grammar.py +459 -0
  24. delphi_lsp/incremental.py +1139 -0
  25. delphi_lsp/lark_builder.py +2684 -0
  26. delphi_lsp/lark_tokens.py +236 -0
  27. delphi_lsp/lexical_scanner.py +30 -0
  28. delphi_lsp/lsp_server.py +6698 -0
  29. delphi_lsp/metrics.py +1452 -0
  30. delphi_lsp/native_bridge.py +300 -0
  31. delphi_lsp/navigation_cache.py +189 -0
  32. delphi_lsp/nodes.py +462 -0
  33. delphi_lsp/parallel_outline.py +662 -0
  34. delphi_lsp/parse_artifacts.py +969 -0
  35. delphi_lsp/parser.py +342 -0
  36. delphi_lsp/parser_backend.py +139 -0
  37. delphi_lsp/preprocessor.py +1122 -0
  38. delphi_lsp/progress.py +26 -0
  39. delphi_lsp/project_config.py +285 -0
  40. delphi_lsp/project_discovery.py +932 -0
  41. delphi_lsp/project_indexer.py +470 -0
  42. delphi_lsp/py.typed +1 -0
  43. delphi_lsp/response_cache.py +465 -0
  44. delphi_lsp/semantic.py +394 -0
  45. delphi_lsp/semantic_builder.py +2302 -0
  46. delphi_lsp/source_reader.py +17 -0
  47. delphi_lsp/wiki_external_sort.py +392 -0
  48. delphi_lsp/wiki_memory.py +548 -0
  49. delphi_lsp/workspace.py +83 -0
  50. delphi_lsp/writer.py +73 -0
  51. python_delphi_lsp-3.6.0.dist-info/METADATA +766 -0
  52. python_delphi_lsp-3.6.0.dist-info/RECORD +56 -0
  53. python_delphi_lsp-3.6.0.dist-info/WHEEL +4 -0
  54. python_delphi_lsp-3.6.0.dist-info/entry_points.txt +3 -0
  55. python_delphi_lsp-3.6.0.dist-info/licenses/LICENSE +373 -0
  56. python_delphi_lsp-3.6.0.dist-info/sboms/python-delphi-lsp.cyclonedx.json +770 -0
@@ -0,0 +1,2684 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable, Iterable
4
+ from typing import Any
5
+
6
+ from .consts import AttributeName, SyntaxNodeType
7
+ from .nodes import CompoundSyntaxNode, SyntaxNode, ValuedSyntaxNode
8
+
9
+
10
+ def build_syntax_tree(
11
+ tree: Any,
12
+ file_name: str,
13
+ *,
14
+ string_transform: Callable[[str], str] | None = None,
15
+ ) -> SyntaxNode:
16
+ try:
17
+ from lark import Transformer, v_args
18
+ from lark.lexer import Token
19
+ except ImportError as exc: # pragma: no cover - runtime dependency
20
+ raise RuntimeError('lark is required to build the syntax tree') from exc
21
+
22
+ def is_token(value: Any) -> bool:
23
+ return isinstance(value, Token)
24
+
25
+ def apply_string(value: str, token_type: str | None = None) -> str:
26
+ if string_transform is None:
27
+ return value
28
+ if token_type is None or token_type in {
29
+ 'NAME',
30
+ 'GENERIC_NAME',
31
+ 'SPACED_GENERIC_NAME',
32
+ 'STRICT_NAME',
33
+ 'STRING_LITERAL',
34
+ 'STRING_BLOCK3',
35
+ 'STRING_BLOCK5',
36
+ }:
37
+ return string_transform(value)
38
+ return value
39
+
40
+ def token_value(value: Any) -> str:
41
+ if is_token(value):
42
+ return apply_string(value.value, value.type)
43
+ return apply_string(str(value))
44
+
45
+ @v_args(meta=True, inline=True)
46
+ class Builder(Transformer):
47
+ def __init__(self) -> None:
48
+ super().__init__()
49
+ self.file_name = file_name
50
+
51
+ def __default__(self, data: str, children: list[Any], meta: Any) -> Any:
52
+ items: list[Any] = []
53
+ for child in children:
54
+ items.extend(self._flatten(child))
55
+ nodes = [child for child in items if isinstance(child, SyntaxNode)]
56
+ if not nodes:
57
+ return None
58
+ if len(nodes) == 1:
59
+ return nodes[0]
60
+ return nodes
61
+
62
+ def __default_token__(self, token: Any) -> Any:
63
+ return token
64
+
65
+ def unit_file(self, meta: Any, *children: Any) -> SyntaxNode:
66
+ unit_name = 'unit'
67
+ directives: dict[str, str] = {}
68
+ for item in self._flatten(children):
69
+ if self._is_text(item):
70
+ unit_name = item
71
+ break
72
+ for item in self._flatten(children):
73
+ if isinstance(item, dict):
74
+ directives.update(item)
75
+ root = self._make_node(SyntaxNodeType.ntUnit, meta)
76
+ root.set_attribute(AttributeName.anName, unit_name)
77
+ self._apply_decl_directives(root, directives)
78
+ for child in children:
79
+ if isinstance(child, SyntaxNode):
80
+ root.add_child(child)
81
+ return root
82
+
83
+ def include_file(self, meta: Any, *children: Any) -> SyntaxNode:
84
+ name = file_name.replace('\\', '/').rsplit('/', 1)[-1].rsplit('.', 1)[0] or 'include'
85
+ root = self._make_node(SyntaxNodeType.ntUnit, meta)
86
+ root.set_attribute(AttributeName.anName, name)
87
+ for child in self._flatten(children):
88
+ if isinstance(child, SyntaxNode):
89
+ root.add_child(child)
90
+ return root
91
+
92
+ def program_file(self, meta: Any, *children: Any) -> SyntaxNode:
93
+ return self._build_program_root(meta, 'program', children)
94
+
95
+ def library_file(self, meta: Any, *children: Any) -> SyntaxNode:
96
+ return self._build_program_root(meta, 'library', children)
97
+
98
+ def package_file(self, meta: Any, *children: Any) -> SyntaxNode:
99
+ unit_name = self._extract_name(children, default='package')
100
+ root = self._make_node(SyntaxNodeType.ntPackage, meta)
101
+ root.set_attribute(AttributeName.anName, unit_name)
102
+ for child in children:
103
+ if isinstance(child, SyntaxNode):
104
+ root.add_child(child)
105
+ elif isinstance(child, list):
106
+ for item in child:
107
+ if isinstance(item, SyntaxNode):
108
+ root.add_child(item)
109
+ return root
110
+
111
+ def unit_header(self, meta: Any, *children: Any) -> list[Any]:
112
+ name = 'unit'
113
+ directives: dict[str, str] = {}
114
+ for child in children:
115
+ if self._is_text(child):
116
+ name = child
117
+ break
118
+ for child in children:
119
+ if isinstance(child, dict):
120
+ directives.update(child)
121
+ return [name, directives]
122
+
123
+ def program_header(self, meta: Any, *children: Any) -> list[Any]:
124
+ name = self._extract_name(children, default='program')
125
+ nodes = [child for child in children if isinstance(child, SyntaxNode)]
126
+ return [name, *nodes]
127
+
128
+ def library_header(self, meta: Any, *children: Any) -> list[Any]:
129
+ name = self._extract_name(children, default='library')
130
+ nodes = [child for child in children if isinstance(child, SyntaxNode)]
131
+ return [name, *nodes]
132
+
133
+ def package_header(self, meta: Any, *children: Any) -> str:
134
+ return self._extract_name(children, default='package')
135
+
136
+ def unit_directive_list(self, meta: Any, *children: Any) -> dict[str, str]:
137
+ attrs: dict[str, str] = {}
138
+ for child in children:
139
+ if isinstance(child, tuple):
140
+ key, value = child
141
+ attrs[key] = value
142
+ return attrs
143
+
144
+ def unit_directive(self, meta: Any, *children: Any) -> tuple[str, str]:
145
+ return self.decl_directive(meta, *children)
146
+
147
+ def program_body(self, meta: Any, *children: Any) -> list[SyntaxNode]:
148
+ return [child for child in self._flatten(children) if isinstance(child, SyntaxNode)]
149
+
150
+ def package_body(self, meta: Any, *children: Any) -> list[SyntaxNode]:
151
+ return [child for child in self._flatten(children) if isinstance(child, SyntaxNode)]
152
+
153
+ def interface_section(self, meta: Any, *children: Any) -> SyntaxNode:
154
+ node = self._make_compound(SyntaxNodeType.ntInterface, meta)
155
+ for child in children:
156
+ if isinstance(child, SyntaxNode):
157
+ node.add_child(child)
158
+ elif isinstance(child, list):
159
+ for item in child:
160
+ if isinstance(item, SyntaxNode):
161
+ node.add_child(item)
162
+ return node
163
+
164
+ def interface_preamble(self, meta: Any, *_: Any) -> None:
165
+ return None
166
+
167
+ def implementation_section(self, meta: Any, *children: Any) -> SyntaxNode:
168
+ node = self._make_compound(SyntaxNodeType.ntImplementation, meta)
169
+ for child in children:
170
+ if isinstance(child, SyntaxNode):
171
+ node.add_child(child)
172
+ elif isinstance(child, list):
173
+ for item in child:
174
+ if isinstance(item, SyntaxNode):
175
+ node.add_child(item)
176
+ return node
177
+
178
+ def initialization_section(self, meta: Any, *children: Any) -> SyntaxNode:
179
+ node = self._make_compound(SyntaxNodeType.ntInitialization, meta)
180
+ for child in children:
181
+ if isinstance(child, SyntaxNode):
182
+ node.add_child(child)
183
+ elif isinstance(child, list):
184
+ for item in child:
185
+ if isinstance(item, SyntaxNode):
186
+ node.add_child(item)
187
+ return node
188
+
189
+ def bare_initialization_section(self, meta: Any, *children: Any) -> SyntaxNode:
190
+ return self.initialization_section(meta, *children)
191
+
192
+ def finalization_section(self, meta: Any, *children: Any) -> SyntaxNode:
193
+ node = self._make_compound(SyntaxNodeType.ntFinalization, meta)
194
+ for child in children:
195
+ if isinstance(child, SyntaxNode):
196
+ node.add_child(child)
197
+ elif isinstance(child, list):
198
+ for item in child:
199
+ if isinstance(item, SyntaxNode):
200
+ node.add_child(item)
201
+ return node
202
+
203
+ def decl_sections(self, meta: Any, *children: Any) -> list[SyntaxNode]:
204
+ nodes: list[SyntaxNode] = []
205
+ for child in children:
206
+ if isinstance(child, list):
207
+ for item in child:
208
+ if isinstance(item, SyntaxNode):
209
+ nodes.append(item)
210
+ elif isinstance(child, SyntaxNode):
211
+ nodes.append(child)
212
+ return nodes
213
+
214
+ def interface_decl_sections(self, meta: Any, *children: Any) -> list[SyntaxNode]:
215
+ return self.decl_sections(meta, *children)
216
+
217
+ def implementation_decl_sections(self, meta: Any, *children: Any) -> list[SyntaxNode]:
218
+ return self.decl_sections(meta, *children)
219
+
220
+ def ignored_proc_type_directive(self, meta: Any, *_: Any) -> None:
221
+ return None
222
+
223
+ def ignored_compiler_error_line(self, meta: Any, *_: Any) -> None:
224
+ return None
225
+
226
+ def block_decl_sections(self, meta: Any, *children: Any) -> list[SyntaxNode]:
227
+ return self.decl_sections(meta, *children)
228
+
229
+ def uses_clause(self, meta: Any, *children: Any) -> SyntaxNode:
230
+ node = self._make_compound(SyntaxNodeType.ntUses, meta)
231
+ for child in children:
232
+ if isinstance(child, SyntaxNode):
233
+ node.add_child(child)
234
+ return node
235
+
236
+ def uses_item(self, meta: Any, *children: Any) -> SyntaxNode:
237
+ name = None
238
+ path = None
239
+ for child in children:
240
+ if self._is_text(child):
241
+ name = child
242
+ elif is_token(child) and child.type == 'STRING_LITERAL':
243
+ path = self._dequote_string(child.value)
244
+ elif isinstance(child, ValuedSyntaxNode):
245
+ path = child.value
246
+ if name is None:
247
+ name = 'unit'
248
+ node = self._make_node(SyntaxNodeType.ntUnit, meta)
249
+ node.set_attribute(AttributeName.anName, name)
250
+ if path:
251
+ node.set_attribute(AttributeName.anPath, path)
252
+ return node
253
+
254
+ def label_section(self, meta: Any, *children: Any) -> list[SyntaxNode]:
255
+ labels: list[SyntaxNode] = []
256
+ for child in self._flatten(children):
257
+ if isinstance(child, str):
258
+ node = self._make_node(SyntaxNodeType.ntLabel, meta)
259
+ node.set_attribute(AttributeName.anName, child)
260
+ labels.append(node)
261
+ return labels
262
+
263
+ def label_list(self, meta: Any, *children: Any) -> list[str]:
264
+ values: list[str] = []
265
+ for child in children:
266
+ if self._is_text(child):
267
+ values.append(child)
268
+ elif is_token(child):
269
+ values.append(child.value)
270
+ return values
271
+
272
+ def label(self, meta: Any, token: Any) -> str:
273
+ return token_value(token)
274
+
275
+ def const_section(self, meta: Any, *children: Any) -> SyntaxNode:
276
+ node = self._make_node(SyntaxNodeType.ntConstants, meta)
277
+ for child in children:
278
+ if isinstance(child, SyntaxNode):
279
+ node.add_child(child)
280
+ return node
281
+
282
+ def resourcestring_section(self, meta: Any, *children: Any) -> SyntaxNode:
283
+ node = self._make_node(SyntaxNodeType.ntResourceString, meta)
284
+ for child in children:
285
+ if isinstance(child, SyntaxNode):
286
+ node.add_child(child)
287
+ return node
288
+
289
+ def const_decl(self, meta: Any, *children: Any) -> SyntaxNode:
290
+ name = None
291
+ attributes: list[SyntaxNode] = []
292
+ directives: dict[str, str] = {}
293
+ for child in children:
294
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAttributes:
295
+ attributes.append(child)
296
+ elif isinstance(child, dict):
297
+ directives.update(child)
298
+ elif self._is_text(child):
299
+ name = child
300
+ elif is_token(child) and child.type == 'NAME':
301
+ name = child.value
302
+ if name is None:
303
+ name = 'const'
304
+ node = self._make_node(SyntaxNodeType.ntConstant, meta)
305
+ node.add_child(self._make_valued(SyntaxNodeType.ntName, name, meta))
306
+ for attr in attributes:
307
+ node.add_child(attr)
308
+ for child in children:
309
+ if isinstance(child, SyntaxNode):
310
+ if child.typ == SyntaxNodeType.ntType:
311
+ node.add_child(child)
312
+ else:
313
+ value_node = self._make_node(SyntaxNodeType.ntValue, meta)
314
+ value_node.add_child(child)
315
+ node.add_child(value_node)
316
+ self._apply_decl_directives(node, directives)
317
+ return node
318
+
319
+ def var_section(self, meta: Any, *children: Any) -> SyntaxNode:
320
+ node = self._make_node(SyntaxNodeType.ntVariables, meta)
321
+ for child in children:
322
+ if isinstance(child, list):
323
+ for var_node in child:
324
+ node.add_child(var_node)
325
+ elif isinstance(child, SyntaxNode):
326
+ node.add_child(child)
327
+ return node
328
+
329
+ def threadvar_section(self, meta: Any, *children: Any) -> SyntaxNode:
330
+ node = self.var_section(meta, *children)
331
+ node.set_attribute(AttributeName.anKind, 'threadvar')
332
+ return node
333
+
334
+ def class_var_section(self, meta: Any, *children: Any) -> SyntaxNode:
335
+ node = self.var_section(meta, *children)
336
+ node.set_attribute(AttributeName.anKind, 'class var')
337
+ return node
338
+
339
+ def class_threadvar_section(self, meta: Any, *children: Any) -> SyntaxNode:
340
+ node = self.var_section(meta, *children)
341
+ node.set_attribute(AttributeName.anKind, 'class threadvar')
342
+ return node
343
+
344
+ def var_decl(self, meta: Any, *children: Any) -> list[SyntaxNode]:
345
+ names: list[str] = []
346
+ type_node = None
347
+ value_expr = None
348
+ absolute_expr = None
349
+ attributes: list[SyntaxNode] = []
350
+ directives: dict[str, str] = {}
351
+ for child in children:
352
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAttributes:
353
+ attributes.append(child)
354
+ elif isinstance(child, list):
355
+ names = child
356
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
357
+ type_node = child
358
+ elif isinstance(child, dict):
359
+ directives.update(child)
360
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAbsolute:
361
+ absolute_expr = child
362
+ elif isinstance(child, SyntaxNode):
363
+ value_expr = child
364
+ variables: list[SyntaxNode] = []
365
+ if type_node is None:
366
+ return variables
367
+ if directives:
368
+ self._apply_directives(type_node, directives)
369
+ for name in names:
370
+ node = self._make_node(SyntaxNodeType.ntVariable, meta)
371
+ node.add_child(self._make_valued(SyntaxNodeType.ntName, name, meta))
372
+ node.add_child(type_node.clone())
373
+ for attr in attributes:
374
+ node.add_child(attr)
375
+ if absolute_expr is not None:
376
+ node.add_child(absolute_expr.clone())
377
+ if value_expr is not None:
378
+ value_node = self._make_node(SyntaxNodeType.ntValue, meta)
379
+ value_node.add_child(value_expr)
380
+ node.add_child(value_node)
381
+ variables.append(node)
382
+ return variables
383
+
384
+ def absolute_spec(self, meta: Any, *children: Any) -> SyntaxNode:
385
+ node = self._make_node(SyntaxNodeType.ntAbsolute, meta)
386
+ for child in children:
387
+ if isinstance(child, SyntaxNode):
388
+ node.add_child(child)
389
+ return node
390
+
391
+ def type_section(self, meta: Any, *children: Any) -> SyntaxNode:
392
+ node = self._make_node(SyntaxNodeType.ntTypeSection, meta)
393
+ for child in children:
394
+ if isinstance(child, SyntaxNode):
395
+ node.add_child(child)
396
+ return node
397
+
398
+ def type_decl(self, meta: Any, *children: Any) -> SyntaxNode:
399
+ name = None
400
+ type_node = None
401
+ type_params = None
402
+ attributes: list[SyntaxNode] = []
403
+ directives: dict[str, str] = {}
404
+ for child in children:
405
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAttributes:
406
+ attributes.append(child)
407
+ elif isinstance(child, dict):
408
+ directives.update(child)
409
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntTypeParams:
410
+ type_params = child
411
+ elif self._is_text(child):
412
+ name = child
413
+ elif is_token(child) and child.type in {'NAME', 'GENERIC_NAME'}:
414
+ name = child.value
415
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
416
+ type_node = child
417
+ if name is None or type_node is None:
418
+ return self._make_compound(SyntaxNodeType.ntTypeDecl, meta)
419
+ if '<' in name:
420
+ base_name, generic_args = self._split_generic_name(name)
421
+ name = base_name
422
+ if type_params is None and generic_args:
423
+ type_params = self._type_params_from_generic_name(meta, generic_args)
424
+ node = self._make_compound(SyntaxNodeType.ntTypeDecl, meta)
425
+ node.set_attribute(AttributeName.anName, name)
426
+ for attr in attributes:
427
+ node.add_child(attr)
428
+ if type_params is not None:
429
+ node.add_child(type_params)
430
+ if directives:
431
+ self._apply_directives(type_node, directives)
432
+ node.add_child(type_node)
433
+ self._apply_decl_directives(node, directives)
434
+ return node
435
+
436
+ def incomplete_type_decl(self, meta: Any, *children: Any) -> SyntaxNode:
437
+ name = None
438
+ type_params = None
439
+ attributes: list[SyntaxNode] = []
440
+ for child in children:
441
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAttributes:
442
+ attributes.append(child)
443
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntTypeParams:
444
+ type_params = child
445
+ elif self._is_text(child):
446
+ name = child
447
+ elif is_token(child) and child.type in {'NAME', 'GENERIC_NAME'}:
448
+ name = child.value
449
+ node = self._make_compound(SyntaxNodeType.ntTypeDecl, meta)
450
+ if name is not None:
451
+ node.set_attribute(AttributeName.anName, name)
452
+ for attr in attributes:
453
+ node.add_child(attr)
454
+ if type_params is not None:
455
+ node.add_child(type_params)
456
+ unknown = self._make_node(SyntaxNodeType.ntType, meta)
457
+ unknown.set_attribute(AttributeName.anType, 'unknown')
458
+ node.add_child(unknown)
459
+ return node
460
+
461
+ def type_decl_name(self, meta: Any, token: Any) -> str:
462
+ return token_value(token)
463
+
464
+ def decl_directive_list(self, meta: Any, *children: Any) -> dict[str, str]:
465
+ attrs: dict[str, str] = {}
466
+ for child in children:
467
+ if isinstance(child, tuple):
468
+ key, value = child
469
+ attrs[key] = value
470
+ return attrs
471
+
472
+ def decl_directive(self, meta: Any, *children: Any) -> tuple[str, str]:
473
+ token = None
474
+ str_token = None
475
+ for child in children:
476
+ if is_token(child) and child.type in {'DEPRECATED', 'PLATFORM', 'EXPERIMENTAL', 'LIBRARY'}:
477
+ token = child
478
+ elif is_token(child) and child.type == 'STRING_LITERAL':
479
+ str_token = child
480
+ if token is None:
481
+ return ('', '')
482
+ key = token.type.lower()
483
+ if key == 'deprecated' and str_token is not None:
484
+ return ('deprecated', self._dequote_string(str_token.value))
485
+ return (key, 'true')
486
+
487
+ def simple_type(self, meta: Any, *children: Any) -> SyntaxNode:
488
+ for child in children:
489
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
490
+ return child
491
+ if self._is_text(child):
492
+ node = self._make_node(SyntaxNodeType.ntType, meta)
493
+ node.set_attribute(AttributeName.anName, child)
494
+ return node
495
+ return self._make_node(SyntaxNodeType.ntType, meta)
496
+
497
+ def type_name(self, meta: Any, *children: Any) -> SyntaxNode:
498
+ name = None
499
+ type_args = None
500
+ for child in children:
501
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntTypeArgs:
502
+ type_args = child
503
+ elif self._is_text(child):
504
+ name = child
505
+ node = self._make_node(SyntaxNodeType.ntType, meta)
506
+ if name is not None:
507
+ node.set_attribute(AttributeName.anName, name)
508
+ if type_args is not None:
509
+ node.add_child(type_args)
510
+ return node
511
+
512
+ def pointer_type(self, meta: Any, *children: Any) -> SyntaxNode:
513
+ node = self._make_node(SyntaxNodeType.ntType, meta)
514
+ node.set_attribute(AttributeName.anType, 'pointer')
515
+ for child in children:
516
+ if isinstance(child, SyntaxNode):
517
+ node.add_child(child)
518
+ elif is_token(child) and child.type == 'POINTER_CHAR':
519
+ target = self._make_node(SyntaxNodeType.ntType, meta)
520
+ target.set_attribute(AttributeName.anName, child.value[1:])
521
+ node.add_child(target)
522
+ return node
523
+
524
+ def distinct_type(self, meta: Any, *children: Any) -> SyntaxNode:
525
+ node = self._make_node(SyntaxNodeType.ntType, meta)
526
+ node.set_attribute(AttributeName.anType, 'distinct')
527
+ for child in children:
528
+ if isinstance(child, SyntaxNode):
529
+ node.add_child(child)
530
+ return node
531
+
532
+ def array_type(self, meta: Any, *children: Any) -> SyntaxNode:
533
+ node = self._make_node(SyntaxNodeType.ntType, meta)
534
+ node.set_attribute(AttributeName.anType, 'array')
535
+ for child in children:
536
+ if isinstance(child, SyntaxNode):
537
+ node.add_child(child)
538
+ return node
539
+
540
+ def array_of_const_type(self, meta: Any, *_: Any) -> SyntaxNode:
541
+ node = self._make_node(SyntaxNodeType.ntType, meta)
542
+ node.set_attribute(AttributeName.anType, 'array')
543
+ const_node = self._make_node(SyntaxNodeType.ntType, meta)
544
+ const_node.set_attribute(AttributeName.anName, 'const')
545
+ node.add_child(const_node)
546
+ return node
547
+
548
+ def array_bounds(self, meta: Any, *children: Any) -> SyntaxNode:
549
+ node = self._make_node(SyntaxNodeType.ntBounds, meta)
550
+ for child in children:
551
+ if isinstance(child, SyntaxNode):
552
+ node.add_child(child)
553
+ return node
554
+
555
+ def array_bound(self, meta: Any, *children: Any) -> SyntaxNode:
556
+ nodes = [child for child in children if isinstance(child, SyntaxNode)]
557
+ if len(nodes) == 2:
558
+ subrange = self._make_node(SyntaxNodeType.ntSubrange, meta)
559
+ subrange.add_child(nodes[0])
560
+ subrange.add_child(nodes[1])
561
+ return subrange
562
+ if nodes:
563
+ return nodes[0]
564
+ return self._make_node(SyntaxNodeType.ntExpression, meta)
565
+
566
+ def set_type(self, meta: Any, *children: Any) -> SyntaxNode:
567
+ node = self._make_node(SyntaxNodeType.ntType, meta)
568
+ node.set_attribute(AttributeName.anType, 'set')
569
+ for child in children:
570
+ if isinstance(child, SyntaxNode):
571
+ node.add_child(child)
572
+ return node
573
+
574
+ def enum_type(self, meta: Any, *children: Any) -> SyntaxNode:
575
+ node = self._make_node(SyntaxNodeType.ntType, meta)
576
+ node.set_attribute(AttributeName.anName, 'enum')
577
+ for child in children:
578
+ if isinstance(child, SyntaxNode):
579
+ node.add_child(child)
580
+ return node
581
+
582
+ def enum_item(self, meta: Any, *children: Any) -> SyntaxNode:
583
+ name = None
584
+ value_expr = None
585
+ for child in children:
586
+ if self._is_text(child):
587
+ name = child
588
+ elif isinstance(child, SyntaxNode):
589
+ value_expr = child
590
+ node = self._make_node(SyntaxNodeType.ntEnum, meta)
591
+ if name:
592
+ node.add_child(self._make_valued(SyntaxNodeType.ntName, name, meta))
593
+ if value_expr is not None:
594
+ value_node = self._make_node(SyntaxNodeType.ntValue, meta)
595
+ value_node.add_child(value_expr)
596
+ node.add_child(value_node)
597
+ return node
598
+
599
+ def string_type(self, meta: Any, *children: Any) -> SyntaxNode:
600
+ node = self._make_node(SyntaxNodeType.ntType, meta)
601
+ node.set_attribute(AttributeName.anName, 'string')
602
+ for child in children:
603
+ if isinstance(child, SyntaxNode):
604
+ node.add_child(child)
605
+ return node
606
+
607
+ def file_type(self, meta: Any, *children: Any) -> SyntaxNode:
608
+ node = self._make_node(SyntaxNodeType.ntType, meta)
609
+ node.set_attribute(AttributeName.anType, 'file')
610
+ for child in children:
611
+ if isinstance(child, SyntaxNode):
612
+ node.add_child(child)
613
+ return node
614
+
615
+ def class_of_type(self, meta: Any, *children: Any) -> SyntaxNode:
616
+ node = self._make_node(SyntaxNodeType.ntType, meta)
617
+ node.set_attribute(AttributeName.anType, 'class of')
618
+ for child in children:
619
+ if isinstance(child, SyntaxNode):
620
+ node.add_child(child)
621
+ return node
622
+
623
+ def reference_type(self, meta: Any, *children: Any) -> SyntaxNode:
624
+ node = self._make_node(SyntaxNodeType.ntType, meta)
625
+ node.set_attribute(AttributeName.anType, 'reference')
626
+ for child in children:
627
+ if isinstance(child, SyntaxNode):
628
+ node.add_child(child)
629
+ return node
630
+
631
+ def packed_type(self, meta: Any, *children: Any) -> SyntaxNode:
632
+ node = self._make_node(SyntaxNodeType.ntType, meta)
633
+ node.set_attribute(AttributeName.anType, 'packed')
634
+ for child in children:
635
+ if isinstance(child, SyntaxNode):
636
+ node.add_child(child)
637
+ return node
638
+
639
+ def subrange_type(self, meta: Any, lower: Any, upper: Any) -> SyntaxNode:
640
+ node = self._make_node(SyntaxNodeType.ntType, meta)
641
+ node.set_attribute(AttributeName.anName, 'subrange')
642
+ bounds = self._make_node(SyntaxNodeType.ntBounds, meta)
643
+ bounds.add_child(self._ensure_expr_node(meta, lower))
644
+ bounds.add_child(self._ensure_expr_node(meta, upper))
645
+ node.add_child(bounds)
646
+ return node
647
+
648
+ def class_type(self, meta: Any, *children: Any) -> SyntaxNode:
649
+ node = self._make_node(SyntaxNodeType.ntType, meta)
650
+ node.set_attribute(AttributeName.anType, 'class')
651
+ for child in children:
652
+ if isinstance(child, SyntaxNode):
653
+ node.add_child(child)
654
+ elif isinstance(child, list):
655
+ for item in child:
656
+ if isinstance(item, SyntaxNode):
657
+ node.add_child(item)
658
+ elif isinstance(child, set):
659
+ if 'abstract' in child:
660
+ node.set_attribute(AttributeName.anAbstract, 'true')
661
+ if 'sealed' in child:
662
+ node.set_attribute(AttributeName.anSealed, 'true')
663
+ return node
664
+
665
+ def class_modifiers(self, meta: Any, *children: Any) -> set[str]:
666
+ return {
667
+ token_value(child).casefold()
668
+ for child in children
669
+ if self._is_text(child) or is_token(child)
670
+ }
671
+
672
+ def forward_class_decl(self, meta: Any, *children: Any) -> SyntaxNode:
673
+ node = self._make_node(SyntaxNodeType.ntType, meta)
674
+ node.set_attribute(AttributeName.anType, 'class')
675
+ for child in children:
676
+ if isinstance(child, SyntaxNode):
677
+ node.add_child(child)
678
+ elif isinstance(child, list):
679
+ for item in child:
680
+ if isinstance(item, SyntaxNode):
681
+ node.add_child(item)
682
+ return node
683
+
684
+ def forward_interface_decl(self, meta: Any, *children: Any) -> SyntaxNode:
685
+ node = self._make_node(SyntaxNodeType.ntType, meta)
686
+ node.set_attribute(AttributeName.anType, 'interface')
687
+ for child in children:
688
+ if isinstance(child, SyntaxNode):
689
+ node.add_child(child)
690
+ elif isinstance(child, list):
691
+ for item in child:
692
+ if isinstance(item, SyntaxNode):
693
+ node.add_child(item)
694
+ return node
695
+
696
+ def forward_dispinterface_decl(self, meta: Any, *children: Any) -> SyntaxNode:
697
+ node = self._make_node(SyntaxNodeType.ntType, meta)
698
+ node.set_attribute(AttributeName.anType, 'dispinterface')
699
+ for child in children:
700
+ if isinstance(child, SyntaxNode):
701
+ node.add_child(child)
702
+ elif isinstance(child, list):
703
+ for item in child:
704
+ if isinstance(item, SyntaxNode):
705
+ node.add_child(item)
706
+ return node
707
+
708
+ def record_type(self, meta: Any, *children: Any) -> SyntaxNode:
709
+ node = self._make_node(SyntaxNodeType.ntType, meta)
710
+ node.set_attribute(AttributeName.anType, 'record')
711
+ for child in children:
712
+ if isinstance(child, list):
713
+ for item in child:
714
+ if isinstance(item, tuple) and item and item[0] == 'align':
715
+ node.set_attribute(AttributeName.anAlign, item[1])
716
+ else:
717
+ node.add_child(item)
718
+ elif isinstance(child, tuple) and child and child[0] == 'align':
719
+ node.set_attribute(AttributeName.anAlign, child[1])
720
+ elif isinstance(child, SyntaxNode):
721
+ node.add_child(child)
722
+ return node
723
+
724
+ def record_align(self, meta: Any, *children: Any) -> tuple[str, str]:
725
+ for child in children:
726
+ if isinstance(child, SyntaxNode):
727
+ value = self._expr_to_text(child)
728
+ if value:
729
+ return ('align', value)
730
+ if self._is_text(child) or is_token(child):
731
+ return ('align', token_value(child))
732
+ return ('align', 'true')
733
+
734
+ def object_type(self, meta: Any, *children: Any) -> SyntaxNode:
735
+ node = self._make_node(SyntaxNodeType.ntType, meta)
736
+ node.set_attribute(AttributeName.anType, 'object')
737
+ for child in children:
738
+ if isinstance(child, SyntaxNode):
739
+ node.add_child(child)
740
+ elif isinstance(child, list):
741
+ for item in child:
742
+ node.add_child(item)
743
+ return node
744
+
745
+ def interface_type(self, meta: Any, *children: Any) -> SyntaxNode:
746
+ node = self._make_node(SyntaxNodeType.ntType, meta)
747
+ token = children[0] if children else None
748
+ if is_token(token) and token.type == 'DISPINTERFACE':
749
+ node.set_attribute(AttributeName.anType, 'dispinterface')
750
+ start_index = 1
751
+ else:
752
+ node.set_attribute(AttributeName.anType, 'interface')
753
+ start_index = 0
754
+ for child in children[start_index:]:
755
+ if isinstance(child, SyntaxNode):
756
+ node.add_child(child)
757
+ elif isinstance(child, list):
758
+ for item in child:
759
+ node.add_child(item)
760
+ return node
761
+
762
+ def helper_type(self, meta: Any, *children: Any) -> SyntaxNode:
763
+ node = self._make_node(SyntaxNodeType.ntType, meta)
764
+ node.set_attribute(AttributeName.anType, 'helper')
765
+ for child in children:
766
+ if isinstance(child, SyntaxNode):
767
+ node.add_child(child)
768
+ elif isinstance(child, list):
769
+ for item in child:
770
+ node.add_child(item)
771
+ return node
772
+
773
+ def interface_guid(self, meta: Any, token: Any) -> SyntaxNode:
774
+ node = self._make_node(SyntaxNodeType.ntGuid, meta)
775
+ if is_token(token) and token.type == 'STRING_LITERAL':
776
+ node.set_attribute(AttributeName.anName, self._dequote_string(token.value))
777
+ return node
778
+
779
+ def type_heritage(self, meta: Any, *children: Any) -> list[SyntaxNode]:
780
+ bases = []
781
+ for name in children:
782
+ if isinstance(name, SyntaxNode) and name.typ == SyntaxNodeType.ntType:
783
+ bases.append(name)
784
+ elif self._is_text(name):
785
+ base = self._make_node(SyntaxNodeType.ntType, meta)
786
+ base.set_attribute(AttributeName.anName, name)
787
+ bases.append(base)
788
+ return bases
789
+
790
+ def type_params(self, meta: Any, *children: Any) -> SyntaxNode:
791
+ node = self._make_node(SyntaxNodeType.ntTypeParams, meta)
792
+ for child in children:
793
+ if isinstance(child, list):
794
+ for item in child:
795
+ if isinstance(item, SyntaxNode):
796
+ node.add_child(item)
797
+ elif isinstance(child, SyntaxNode):
798
+ node.add_child(child)
799
+ return node
800
+
801
+ def type_param(self, meta: Any, *children: Any) -> list[SyntaxNode]:
802
+ names: list[str] = []
803
+ constraints = None
804
+ for child in children:
805
+ if isinstance(child, tuple):
806
+ tuple_names, tuple_constraints = child
807
+ names = list(tuple_names)
808
+ constraints = tuple_constraints
809
+ elif isinstance(child, list):
810
+ names = [token_value(item) for item in child]
811
+ elif self._is_text(child):
812
+ names.append(child)
813
+ elif is_token(child) and child.type == 'NAME':
814
+ names.append(token_value(child))
815
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntConstraints:
816
+ constraints = child
817
+ params: list[SyntaxNode] = []
818
+ for name in names:
819
+ node = self._make_node(SyntaxNodeType.ntTypeParam, meta)
820
+ node.add_child(self._make_valued(SyntaxNodeType.ntName, name, meta))
821
+ if constraints is not None:
822
+ node.add_child(constraints.clone())
823
+ params.append(node)
824
+ return params
825
+
826
+ def constrained_name_list(self, meta: Any, *children: Any) -> list[str]:
827
+ return [token_value(child) for child in children]
828
+
829
+ def constrained_type_param(self, meta: Any, names: Any, constraints: Any) -> tuple[list[str], SyntaxNode | None]:
830
+ resolved_names: list[str] = []
831
+ if isinstance(names, list):
832
+ resolved_names = [token_value(name) for name in names]
833
+ elif self._is_text(names):
834
+ resolved_names = [names]
835
+ elif is_token(names):
836
+ resolved_names = [token_value(names)]
837
+ constraint_node = constraints if isinstance(constraints, SyntaxNode) else None
838
+ return (resolved_names, constraint_node)
839
+
840
+ def type_constraints(self, meta: Any, *children: Any) -> SyntaxNode:
841
+ node = self._make_node(SyntaxNodeType.ntConstraints, meta)
842
+ for child in children:
843
+ if isinstance(child, SyntaxNode):
844
+ node.add_child(child)
845
+ return node
846
+
847
+ def type_constraint(self, meta: Any, *children: Any) -> SyntaxNode:
848
+ for child in children:
849
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
850
+ return child
851
+ if is_token(child):
852
+ if child.type == 'CLASS':
853
+ return self._make_node(SyntaxNodeType.ntClassConstraint, meta)
854
+ if child.type == 'RECORD':
855
+ return self._make_node(SyntaxNodeType.ntRecordConstraint, meta)
856
+ if child.type == 'CONSTRUCTOR':
857
+ return self._make_node(SyntaxNodeType.ntConstructorConstraint, meta)
858
+ if child.type == 'INTERFACE':
859
+ return self._make_node(SyntaxNodeType.ntInterfaceConstraint, meta)
860
+ if child.type == 'UNMANAGED':
861
+ return self._make_node(SyntaxNodeType.ntUnmanagedConstraint, meta)
862
+ return self._make_node(SyntaxNodeType.ntUnknown, meta)
863
+
864
+ def type_args(self, meta: Any, *children: Any) -> SyntaxNode:
865
+ node = self._make_node(SyntaxNodeType.ntTypeArgs, meta)
866
+ for child in children:
867
+ if isinstance(child, SyntaxNode):
868
+ node.add_child(child)
869
+ return node
870
+
871
+ def field_list(self, meta: Any, *children: Any) -> list[SyntaxNode]:
872
+ fields: list[SyntaxNode] = []
873
+ for child in children:
874
+ if isinstance(child, list):
875
+ fields.extend(child)
876
+ return fields
877
+
878
+ def field_decl(self, meta: Any, *children: Any) -> list[SyntaxNode]:
879
+ names: list[str] = []
880
+ type_node = None
881
+ attributes: list[SyntaxNode] = []
882
+ directives: dict[str, str] = {}
883
+ for child in children:
884
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAttributes:
885
+ attributes.append(child)
886
+ elif isinstance(child, list):
887
+ names = child
888
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
889
+ type_node = child
890
+ elif isinstance(child, dict):
891
+ directives.update(child)
892
+ fields: list[SyntaxNode] = []
893
+ if type_node is None:
894
+ return fields
895
+ if directives:
896
+ self._apply_directives(type_node, directives)
897
+ for name in names:
898
+ field = self._make_node(SyntaxNodeType.ntField, meta)
899
+ field.add_child(self._make_valued(SyntaxNodeType.ntName, name, meta))
900
+ field.add_child(type_node.clone())
901
+ for attr in attributes:
902
+ field.add_child(attr)
903
+ fields.append(field)
904
+ return fields
905
+
906
+ def proc_type(self, meta: Any, *children: Any) -> SyntaxNode:
907
+ kind = 'procedure'
908
+ params = None
909
+ return_type = None
910
+ for child in children:
911
+ if is_token(child) and child.type == 'FUNCTION':
912
+ kind = 'function'
913
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntParameters:
914
+ params = child
915
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
916
+ return_type = child
917
+ node = self._make_node(SyntaxNodeType.ntType, meta)
918
+ node.set_attribute(AttributeName.anType, kind)
919
+ if params is not None:
920
+ node.add_child(params)
921
+ if return_type is not None:
922
+ return_node = self._make_node(SyntaxNodeType.ntReturnType, meta)
923
+ return_node.add_child(return_type)
924
+ node.add_child(return_node)
925
+ return node
926
+
927
+ def proc_type_decl_directive(self, meta: Any, *children: Any) -> dict[str, str]:
928
+ for child in children:
929
+ if is_token(child):
930
+ values = child.value.lstrip(';').strip().casefold().split()
931
+ return self._proc_type_directive_attrs(values)
932
+ return {}
933
+
934
+ def visibility_spec(self, meta: Any, *children: Any) -> SyntaxNode:
935
+ token = None
936
+ for child in children:
937
+ if is_token(child):
938
+ token = child
939
+ if token is None:
940
+ return self._make_node(SyntaxNodeType.ntPublic, meta)
941
+ mapping = {
942
+ 'PRIVATE': SyntaxNodeType.ntPrivate,
943
+ 'PROTECTED': SyntaxNodeType.ntProtected,
944
+ 'PUBLIC': SyntaxNodeType.ntPublic,
945
+ 'PUBLISHED': SyntaxNodeType.ntPublished,
946
+ 'AUTOMATED': SyntaxNodeType.ntPublished,
947
+ }
948
+ if token.type == 'PRIVATE' and any(is_token(c) and c.type == 'STRICT' for c in children):
949
+ node = self._make_node(SyntaxNodeType.ntStrictPrivate, meta)
950
+ elif token.type == 'PROTECTED' and any(is_token(c) and c.type == 'STRICT' for c in children):
951
+ node = self._make_node(SyntaxNodeType.ntStrictProtected, meta)
952
+ else:
953
+ node = self._make_node(mapping.get(token.type, SyntaxNodeType.ntPublic), meta)
954
+ node.set_attribute(AttributeName.anVisibility, 'true')
955
+ return node
956
+
957
+ def class_member(self, meta: Any, *children: Any) -> list[SyntaxNode]:
958
+ visibility = None
959
+ members: list[SyntaxNode] = []
960
+ for child in children:
961
+ if isinstance(child, SyntaxNode) and child.typ in {
962
+ SyntaxNodeType.ntPrivate,
963
+ SyntaxNodeType.ntProtected,
964
+ SyntaxNodeType.ntPublic,
965
+ SyntaxNodeType.ntPublished,
966
+ SyntaxNodeType.ntStrictPrivate,
967
+ SyntaxNodeType.ntStrictProtected,
968
+ }:
969
+ visibility = child
970
+ elif isinstance(child, list):
971
+ for item in child:
972
+ if isinstance(item, SyntaxNode):
973
+ members.append(item)
974
+ elif isinstance(child, SyntaxNode):
975
+ members.append(child)
976
+ if visibility is None:
977
+ return members
978
+ return [visibility] + members
979
+
980
+ def class_body(self, meta: Any, *children: Any) -> list[SyntaxNode]:
981
+ members: list[SyntaxNode] = []
982
+ current_visibility: SyntaxNode | None = None
983
+ for child in children:
984
+ for item in self._flatten(child):
985
+ if isinstance(item, SyntaxNode) and item.typ in {
986
+ SyntaxNodeType.ntPrivate,
987
+ SyntaxNodeType.ntProtected,
988
+ SyntaxNodeType.ntPublic,
989
+ SyntaxNodeType.ntPublished,
990
+ SyntaxNodeType.ntStrictPrivate,
991
+ SyntaxNodeType.ntStrictProtected,
992
+ }:
993
+ current_visibility = item
994
+ continue
995
+ if isinstance(item, SyntaxNode):
996
+ if current_visibility is not None:
997
+ vis_node = current_visibility.clone()
998
+ vis_node.add_child(item)
999
+ members.append(vis_node)
1000
+ else:
1001
+ members.append(item)
1002
+ return members
1003
+
1004
+ def record_body(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1005
+ return self.class_body(meta, *children)
1006
+
1007
+ def interface_body(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1008
+ return [child for child in children if isinstance(child, SyntaxNode)]
1009
+
1010
+ def interface_member(self, meta: Any, *children: Any) -> SyntaxNode | None:
1011
+ for child in children:
1012
+ if isinstance(child, SyntaxNode):
1013
+ return child
1014
+ return None
1015
+
1016
+ def property_decl(self, meta: Any, *children: Any) -> SyntaxNode:
1017
+ name = None
1018
+ attributes: list[SyntaxNode] = []
1019
+ for child in children:
1020
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAttributes:
1021
+ attributes.append(child)
1022
+ elif self._is_text(child):
1023
+ name = child
1024
+ elif is_token(child) and child.type == 'NAME':
1025
+ name = child.value
1026
+ if name is None:
1027
+ name = 'property'
1028
+ node = self._make_node(SyntaxNodeType.ntProperty, meta)
1029
+ node.set_attribute(AttributeName.anName, token_value(name))
1030
+ for attr in attributes:
1031
+ node.add_child(attr)
1032
+ for child in children:
1033
+ if isinstance(child, list):
1034
+ for item in child:
1035
+ if isinstance(item, SyntaxNode):
1036
+ node.add_child(item)
1037
+ elif isinstance(child, SyntaxNode):
1038
+ node.add_child(child)
1039
+ return node
1040
+
1041
+ def property_directive_block(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1042
+ nodes: list[SyntaxNode] = []
1043
+ for child in children:
1044
+ if isinstance(child, SyntaxNode):
1045
+ nodes.append(child)
1046
+ elif isinstance(child, list):
1047
+ for item in child:
1048
+ if isinstance(item, SyntaxNode):
1049
+ nodes.append(item)
1050
+ return nodes
1051
+
1052
+ def property_directive(self, meta: Any, *children: Any) -> SyntaxNode:
1053
+ token = None
1054
+ expr = None
1055
+ for child in children:
1056
+ if is_token(child):
1057
+ token = child
1058
+ elif isinstance(child, SyntaxNode):
1059
+ expr = child
1060
+ if token is None:
1061
+ return self._make_node(SyntaxNodeType.ntUnknown, meta)
1062
+ mapping = {
1063
+ 'READ': SyntaxNodeType.ntRead,
1064
+ 'WRITE': SyntaxNodeType.ntWrite,
1065
+ 'ADD': SyntaxNodeType.ntUnknown,
1066
+ 'REMOVE': SyntaxNodeType.ntUnknown,
1067
+ 'DEFAULT': SyntaxNodeType.ntDefault,
1068
+ 'STORED': SyntaxNodeType.ntUnknown,
1069
+ 'IMPLEMENTS': SyntaxNodeType.ntImplements,
1070
+ }
1071
+ node = self._make_node(mapping.get(token.type, SyntaxNodeType.ntUnknown), meta)
1072
+ if token.type in {'ADD', 'REMOVE', 'STORED'}:
1073
+ node.set_attribute(AttributeName.anKind, token.type.lower())
1074
+ if expr is not None:
1075
+ node.add_child(expr)
1076
+ return node
1077
+
1078
+ def property_specifier(self, meta: Any, *children: Any) -> SyntaxNode:
1079
+ return self._make_node(SyntaxNodeType.ntUnknown, meta)
1080
+
1081
+ def routine_decl(self, meta: Any, *children: Any) -> SyntaxNode:
1082
+ heading = None
1083
+ body = None
1084
+ directives = None
1085
+ for child in children:
1086
+ if isinstance(child, SyntaxNode):
1087
+ if heading is None:
1088
+ heading = child
1089
+ else:
1090
+ body = child
1091
+ elif isinstance(child, list):
1092
+ body = child
1093
+ elif isinstance(child, dict):
1094
+ directives = child
1095
+ if heading is None:
1096
+ return self._make_node(SyntaxNodeType.ntMethod, meta)
1097
+ if directives:
1098
+ self._apply_directives(heading, directives)
1099
+ if body is not None:
1100
+ if isinstance(body, list):
1101
+ for item in body:
1102
+ if isinstance(item, SyntaxNode):
1103
+ heading.add_child(item)
1104
+ elif isinstance(body, SyntaxNode):
1105
+ heading.add_child(body)
1106
+ return heading
1107
+
1108
+ def resolution_decl(self, meta: Any, *children: Any) -> SyntaxNode:
1109
+ method = None
1110
+ source_name = None
1111
+ target_name = None
1112
+ for child in children:
1113
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntMethod:
1114
+ method = child
1115
+ elif self._is_text(child) or is_token(child):
1116
+ text = token_value(child)
1117
+ if source_name is None:
1118
+ source_name = text
1119
+ else:
1120
+ target_name = text
1121
+ if method is None:
1122
+ method = self._make_node(SyntaxNodeType.ntMethod, meta)
1123
+ if source_name:
1124
+ method.set_attribute(AttributeName.anName, source_name)
1125
+ method.set_attribute(AttributeName.anKind, 'resolution')
1126
+ if target_name:
1127
+ resolution = self._make_node(SyntaxNodeType.ntResolutionClause, meta)
1128
+ resolution.set_attribute(AttributeName.anName, target_name)
1129
+ method.add_child(resolution)
1130
+ return method
1131
+
1132
+ def routine_impl(self, meta: Any, *children: Any) -> SyntaxNode:
1133
+ heading = None
1134
+ body = None
1135
+ directives: dict[str, str] = {}
1136
+ for child in children:
1137
+ if isinstance(child, SyntaxNode):
1138
+ if heading is None:
1139
+ heading = child
1140
+ else:
1141
+ body = child
1142
+ elif isinstance(child, list):
1143
+ body = child
1144
+ elif isinstance(child, dict):
1145
+ directives.update(child)
1146
+ elif isinstance(child, tuple):
1147
+ key, value = child
1148
+ if key:
1149
+ directives[key] = value
1150
+ elif is_token(child):
1151
+ if child.type == 'FORWARD':
1152
+ directives['forwarded'] = 'true'
1153
+ elif child.type == 'EXTERNAL':
1154
+ directives['external'] = 'true'
1155
+ if heading is None:
1156
+ return self._make_node(SyntaxNodeType.ntMethod, meta)
1157
+ if directives:
1158
+ self._apply_directives(heading, directives)
1159
+ if body is not None:
1160
+ if isinstance(body, list):
1161
+ for item in body:
1162
+ if isinstance(item, SyntaxNode):
1163
+ heading.add_child(item)
1164
+ elif isinstance(body, SyntaxNode):
1165
+ heading.add_child(body)
1166
+ return heading
1167
+
1168
+ def procedure_decl(self, meta: Any, *children: Any) -> SyntaxNode:
1169
+ return self._build_routine_from_children(meta, 'procedure', children)
1170
+
1171
+ def function_decl(self, meta: Any, *children: Any) -> SyntaxNode:
1172
+ return self._build_routine_from_children(meta, 'function', children)
1173
+
1174
+ def constructor_decl(self, meta: Any, *children: Any) -> SyntaxNode:
1175
+ return self._build_routine_from_children(meta, 'constructor', children)
1176
+
1177
+ def destructor_decl(self, meta: Any, *children: Any) -> SyntaxNode:
1178
+ return self._build_routine_from_children(meta, 'destructor', children)
1179
+
1180
+ def operator_decl(self, meta: Any, *children: Any) -> SyntaxNode:
1181
+ return self._build_routine_from_children(meta, 'operator', children)
1182
+
1183
+ def routine_body(self, meta: Any, *children: Any) -> SyntaxNode | None:
1184
+ for child in children:
1185
+ if isinstance(child, SyntaxNode):
1186
+ return child
1187
+ if isinstance(child, list):
1188
+ return child
1189
+ if is_token(child) and child.type == 'FORWARD':
1190
+ node = self._make_node(SyntaxNodeType.ntUnknown, meta)
1191
+ node.set_attribute(AttributeName.anForwarded, 'true')
1192
+ return node
1193
+ return None
1194
+
1195
+ def block(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1196
+ nodes: list[SyntaxNode] = []
1197
+ for child in children:
1198
+ if isinstance(child, list):
1199
+ for item in child:
1200
+ if isinstance(item, SyntaxNode):
1201
+ nodes.append(item)
1202
+ elif isinstance(child, SyntaxNode):
1203
+ nodes.append(child)
1204
+ return nodes
1205
+
1206
+ def asm_block(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1207
+ return self.block(meta, *children)
1208
+
1209
+ def directive_list(self, meta: Any, *children: Any) -> dict[str, str]:
1210
+ attrs: dict[str, str] = {}
1211
+ for child in children:
1212
+ if isinstance(child, tuple):
1213
+ key, value = child
1214
+ attrs[key] = value
1215
+ elif isinstance(child, dict):
1216
+ attrs.update(child)
1217
+ return attrs
1218
+
1219
+ def body_directive_list(self, meta: Any, *children: Any) -> dict[str, str]:
1220
+ return self.directive_list(meta, *children)
1221
+
1222
+ def body_directive(self, meta: Any, *children: Any) -> tuple[str, str]:
1223
+ return self.directive(meta, *children)
1224
+
1225
+ def routine_heading_directive_list(self, meta: Any, *children: Any) -> dict[str, str]:
1226
+ attrs: dict[str, str] = {}
1227
+ for child in children:
1228
+ if isinstance(child, tuple):
1229
+ key, value = child
1230
+ if key:
1231
+ attrs[key] = value
1232
+ return attrs
1233
+
1234
+ def routine_heading_directive(self, meta: Any, *children: Any) -> tuple[str, str]:
1235
+ return self.directive(meta, *children)
1236
+
1237
+ def directive(self, meta: Any, *children: Any) -> tuple[str, str]:
1238
+ token = None
1239
+ expr = None
1240
+ directive_tokens = {
1241
+ 'OVERLOAD',
1242
+ 'OVERRIDE',
1243
+ 'VIRTUAL',
1244
+ 'DYNAMIC',
1245
+ 'ABSTRACT',
1246
+ 'INLINE',
1247
+ 'REINTRODUCE',
1248
+ 'STATIC',
1249
+ 'FINAL',
1250
+ 'SEALED',
1251
+ 'STDCALL',
1252
+ 'CDECL',
1253
+ 'PASCAL',
1254
+ 'REGISTER',
1255
+ 'SAFECALL',
1256
+ 'WINAPI',
1257
+ 'MESSAGE',
1258
+ 'EXTERNAL',
1259
+ 'FORWARD',
1260
+ 'DEPRECATED',
1261
+ 'PLATFORM',
1262
+ 'EXPERIMENTAL',
1263
+ 'NORETURN',
1264
+ 'VARARGS',
1265
+ 'LOCAL',
1266
+ 'LIBRARY',
1267
+ 'DELAYED',
1268
+ 'EXPORT',
1269
+ 'FAR',
1270
+ 'NEAR',
1271
+ 'ASSEMBLER',
1272
+ 'UNSAFE',
1273
+ 'DISPID',
1274
+ }
1275
+ for child in children:
1276
+ if is_token(child) and token is None and child.type in directive_tokens:
1277
+ token = child
1278
+ elif isinstance(child, SyntaxNode):
1279
+ expr = child
1280
+ if token is None:
1281
+ return ('', '')
1282
+ name = token.type.lower()
1283
+ if name in {'override', 'virtual', 'dynamic'}:
1284
+ return ('methodbinding', name)
1285
+ if name in {'reintroduce', 'overload', 'abstract', 'inline'}:
1286
+ return (name, 'true')
1287
+ if name in {'stdcall', 'cdecl', 'pascal', 'register', 'safecall'}:
1288
+ return ('callingconvention', name)
1289
+ if name == 'winapi':
1290
+ return ('callingconvention', 'winapi')
1291
+ if name == 'message' and expr is not None:
1292
+ return ('message', self._expr_to_text(expr))
1293
+ if name == 'external':
1294
+ return ('external', 'true')
1295
+ if name == 'forward':
1296
+ return ('forwarded', 'true')
1297
+ if name == 'deprecated':
1298
+ return ('deprecated', self._expr_to_text(expr) if expr is not None else 'true')
1299
+ if name in {
1300
+ 'platform',
1301
+ 'experimental',
1302
+ 'varargs',
1303
+ 'local',
1304
+ 'library',
1305
+ 'delayed',
1306
+ 'static',
1307
+ 'final',
1308
+ 'sealed',
1309
+ 'export',
1310
+ 'far',
1311
+ 'near',
1312
+ 'assembler',
1313
+ 'unsafe',
1314
+ 'noreturn',
1315
+ }:
1316
+ return (name, 'true')
1317
+ if name == 'dispid' and expr is not None:
1318
+ return ('dispid', self._expr_to_text(expr))
1319
+ return ('', '')
1320
+
1321
+ def formal_parameters(self, meta: Any, *children: Any) -> SyntaxNode:
1322
+ node = self._make_node(SyntaxNodeType.ntParameters, meta)
1323
+ for child in children:
1324
+ for param in self._flatten(child):
1325
+ if isinstance(param, SyntaxNode):
1326
+ node.add_child(param)
1327
+ return node
1328
+
1329
+ def param_list(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1330
+ params: list[SyntaxNode] = []
1331
+ for child in children:
1332
+ if isinstance(child, list):
1333
+ params.extend(child)
1334
+ return params
1335
+
1336
+ def param(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1337
+ modifier = None
1338
+ names: list[str] = []
1339
+ type_node = None
1340
+ default_expr = None
1341
+ attributes: list[SyntaxNode] = []
1342
+ for child in children:
1343
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAttributes:
1344
+ attributes.append(child)
1345
+ elif self._is_text(child):
1346
+ names.append(child)
1347
+ elif isinstance(child, list):
1348
+ names = child
1349
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
1350
+ type_node = child
1351
+ elif is_token(child):
1352
+ modifier = child
1353
+ elif isinstance(child, SyntaxNode):
1354
+ default_expr = child
1355
+ params: list[SyntaxNode] = []
1356
+ for name in names:
1357
+ node = self._make_node(SyntaxNodeType.ntParameter, meta)
1358
+ if modifier is not None:
1359
+ node.set_attribute(AttributeName.anKind, modifier.value.lower())
1360
+ node.add_child(self._make_valued(SyntaxNodeType.ntName, name, meta))
1361
+ if type_node is not None:
1362
+ node.add_child(type_node.clone())
1363
+ for attr in attributes:
1364
+ node.add_child(attr)
1365
+ if default_expr is not None:
1366
+ value_node = self._make_node(SyntaxNodeType.ntValue, meta)
1367
+ value_node.add_child(default_expr)
1368
+ node.add_child(value_node)
1369
+ params.append(node)
1370
+ return params
1371
+
1372
+ def param_modifier(self, meta: Any, token: Any) -> Any:
1373
+ return token
1374
+
1375
+ def name_list(self, meta: Any, *children: Any) -> list[str]:
1376
+ return [token_value(child) for child in children]
1377
+
1378
+ def qualified_name(self, meta: Any, *children: Any) -> str:
1379
+ return '.'.join(token_value(child) for child in children)
1380
+
1381
+ def qualified_name_part(self, meta: Any, token: Any) -> str:
1382
+ return token_value(token)
1383
+
1384
+ def expr_identifier(self, meta: Any, token: Any) -> SyntaxNode:
1385
+ name = token_value(token)
1386
+ return self._make_expr_identifier(meta, name)
1387
+
1388
+ def expr_qualified_name(self, meta: Any, *children: Any) -> SyntaxNode:
1389
+ nodes: list[SyntaxNode] = []
1390
+ for child in children:
1391
+ if isinstance(child, list):
1392
+ for item in child:
1393
+ if isinstance(item, SyntaxNode):
1394
+ nodes.append(item)
1395
+ elif self._is_text(item) or is_token(item):
1396
+ nodes.append(self._make_expr_identifier(meta, token_value(item)))
1397
+ elif isinstance(child, SyntaxNode):
1398
+ nodes.append(child)
1399
+ elif self._is_text(child) or is_token(child):
1400
+ nodes.append(self._make_expr_identifier(meta, token_value(child)))
1401
+ if not nodes:
1402
+ return self._make_node(SyntaxNodeType.ntExpression, meta)
1403
+ node = nodes[0]
1404
+ for part in nodes[1:]:
1405
+ dot = self._make_node(SyntaxNodeType.ntDot, meta)
1406
+ dot.add_child(node)
1407
+ dot.add_child(part)
1408
+ node = dot
1409
+ return node
1410
+
1411
+ def literal(self, meta: Any, token: Any) -> SyntaxNode:
1412
+ if isinstance(token, SyntaxNode):
1413
+ return token
1414
+ value = token_value(token)
1415
+ node = self._make_valued(SyntaxNodeType.ntLiteral, value, meta)
1416
+ if is_token(token):
1417
+ if token.type in {'STRING_LITERAL', 'STRING_BLOCK3', 'STRING_BLOCK5'}:
1418
+ node.value = self._dequote_string(value)
1419
+ node.set_attribute(AttributeName.anType, 'string')
1420
+ elif token.type == 'POINTER_CHAR':
1421
+ node.set_attribute(AttributeName.anType, 'char')
1422
+ else:
1423
+ node.set_attribute(AttributeName.anType, 'numeric')
1424
+ return node
1425
+
1426
+ def string_literal_sequence(self, meta: Any, *children: Any) -> SyntaxNode:
1427
+ parts: list[str] = []
1428
+ for child in children:
1429
+ if not is_token(child):
1430
+ continue
1431
+ value = token_value(child)
1432
+ if child.type in {'STRING_LITERAL', 'STRING_BLOCK3', 'STRING_BLOCK5'}:
1433
+ parts.append(self._dequote_string(value))
1434
+ else:
1435
+ parts.append(value)
1436
+ node = self._make_valued(SyntaxNodeType.ntLiteral, ''.join(parts), meta)
1437
+ node.set_attribute(AttributeName.anType, 'string')
1438
+ return node
1439
+
1440
+ def string_literal_part(self, meta: Any, token: Any) -> Any:
1441
+ return token
1442
+
1443
+ def numeric_literal(self, meta: Any, token: Any) -> SyntaxNode:
1444
+ value = token_value(token)
1445
+ node = self._make_valued(SyntaxNodeType.ntLiteral, value, meta)
1446
+ node.set_attribute(AttributeName.anType, 'numeric')
1447
+ return node
1448
+
1449
+ def anonymous_method(self, meta: Any, *children: Any) -> SyntaxNode:
1450
+ kind = None
1451
+ params = None
1452
+ return_type = None
1453
+ body = None
1454
+ for child in children:
1455
+ if is_token(child) and child.type in {'PROCEDURE', 'FUNCTION'}:
1456
+ kind = child.type.lower()
1457
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntParameters:
1458
+ params = child
1459
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
1460
+ return_type = child
1461
+ elif isinstance(child, list) or isinstance(child, SyntaxNode):
1462
+ body = child
1463
+ node = self._make_node(SyntaxNodeType.ntAnonymousMethod, meta)
1464
+ if kind:
1465
+ node.set_attribute(AttributeName.anKind, kind)
1466
+ if params is not None:
1467
+ node.add_child(params)
1468
+ if return_type is not None:
1469
+ return_node = self._make_node(SyntaxNodeType.ntReturnType, meta)
1470
+ return_node.add_child(return_type)
1471
+ node.add_child(return_node)
1472
+ if body is not None:
1473
+ if isinstance(body, list):
1474
+ for item in body:
1475
+ if isinstance(item, SyntaxNode):
1476
+ node.add_child(item)
1477
+ elif isinstance(body, SyntaxNode):
1478
+ node.add_child(body)
1479
+ return node
1480
+
1481
+ def primary(self, meta: Any, child: Any) -> SyntaxNode:
1482
+ if isinstance(child, SyntaxNode):
1483
+ return child
1484
+ if is_token(child) and child.type == 'NIL':
1485
+ node = self._make_valued(SyntaxNodeType.ntLiteral, 'nil', meta)
1486
+ node.set_attribute(AttributeName.anType, 'nil')
1487
+ return node
1488
+ if is_token(child) and child.type in {'TRUE', 'FALSE'}:
1489
+ node = self._make_valued(SyntaxNodeType.ntLiteral, child.value.lower(), meta)
1490
+ node.set_attribute(AttributeName.anType, 'boolean')
1491
+ return node
1492
+ if is_token(child) and child.type == 'SELF':
1493
+ node = self._make_node(SyntaxNodeType.ntIdentifier, meta)
1494
+ node.set_attribute(AttributeName.anName, 'self')
1495
+ return node
1496
+ name = token_value(child)
1497
+ node = self._make_node(SyntaxNodeType.ntIdentifier, meta)
1498
+ node.set_attribute(AttributeName.anName, name)
1499
+ return node
1500
+
1501
+ def expr_list(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1502
+ return [child for child in self._flatten(children) if isinstance(child, SyntaxNode)]
1503
+
1504
+ def if_expr(self, meta: Any, *children: Any) -> SyntaxNode:
1505
+ node = self._make_node(SyntaxNodeType.ntIf, meta)
1506
+ for child in children:
1507
+ if isinstance(child, SyntaxNode):
1508
+ node.add_child(child)
1509
+ return node
1510
+
1511
+ def or_expr(self, meta: Any, *children: Any) -> SyntaxNode:
1512
+ return self._binary_chain(meta, children, {'OR': SyntaxNodeType.ntOr})
1513
+
1514
+ def xor_expr(self, meta: Any, *children: Any) -> SyntaxNode:
1515
+ return self._binary_chain(meta, children, {'XOR': SyntaxNodeType.ntXor})
1516
+
1517
+ def and_expr(self, meta: Any, *children: Any) -> SyntaxNode:
1518
+ return self._binary_chain(meta, children, {'AND': SyntaxNodeType.ntAnd})
1519
+
1520
+ def rel_expr(self, meta: Any, *children: Any) -> SyntaxNode:
1521
+ return self._binary_chain(
1522
+ meta,
1523
+ children,
1524
+ {
1525
+ '=': SyntaxNodeType.ntEqual,
1526
+ '<>': SyntaxNodeType.ntNotEqual,
1527
+ '<': SyntaxNodeType.ntLower,
1528
+ '<=': SyntaxNodeType.ntLowerEqual,
1529
+ '>': SyntaxNodeType.ntGreater,
1530
+ '>=': SyntaxNodeType.ntGreaterEqual,
1531
+ 'IN': SyntaxNodeType.ntIn,
1532
+ 'IS': SyntaxNodeType.ntIs,
1533
+ 'NOT IN': SyntaxNodeType.ntNotIn,
1534
+ 'IS NOT': SyntaxNodeType.ntIsNot,
1535
+ 'AS': SyntaxNodeType.ntAs,
1536
+ },
1537
+ )
1538
+
1539
+ def rel_op(self, meta: Any, *children: Any) -> Any:
1540
+ if children:
1541
+ return children[0]
1542
+ return ''
1543
+
1544
+ def not_in_op(self, meta: Any, *_: Any) -> str:
1545
+ return 'NOT IN'
1546
+
1547
+ def is_not_op(self, meta: Any, *_: Any) -> str:
1548
+ return 'IS NOT'
1549
+
1550
+ def add_expr(self, meta: Any, *children: Any) -> SyntaxNode:
1551
+ return self._binary_chain(
1552
+ meta,
1553
+ children,
1554
+ {'+': SyntaxNodeType.ntAdd, '-': SyntaxNodeType.ntSub},
1555
+ )
1556
+
1557
+ def mul_expr(self, meta: Any, *children: Any) -> SyntaxNode:
1558
+ return self._binary_chain(
1559
+ meta,
1560
+ children,
1561
+ {
1562
+ '*': SyntaxNodeType.ntMul,
1563
+ '/': SyntaxNodeType.ntFDiv,
1564
+ 'DIV': SyntaxNodeType.ntDiv,
1565
+ 'MOD': SyntaxNodeType.ntMod,
1566
+ 'SHL': SyntaxNodeType.ntShl,
1567
+ 'SHR': SyntaxNodeType.ntShr,
1568
+ },
1569
+ )
1570
+
1571
+ def unary_expr(self, meta: Any, *children: Any) -> SyntaxNode:
1572
+ if len(children) == 2 and is_token(children[0]):
1573
+ token = children[0]
1574
+ expr = children[1]
1575
+ if token.type == 'NOT':
1576
+ node = self._make_node(SyntaxNodeType.ntNot, meta)
1577
+ node.add_child(expr)
1578
+ return node
1579
+ if token.value == '@':
1580
+ node = self._make_node(SyntaxNodeType.ntAddr, meta)
1581
+ node.add_child(expr)
1582
+ return node
1583
+ if token.value == '^':
1584
+ node = self._make_node(SyntaxNodeType.ntDeref, meta)
1585
+ node.add_child(expr)
1586
+ return node
1587
+ if token.value == '-':
1588
+ node = self._make_node(SyntaxNodeType.ntUnaryMinus, meta)
1589
+ node.add_child(expr)
1590
+ return node
1591
+ return expr
1592
+ if children:
1593
+ return children[0]
1594
+ return self._make_node(SyntaxNodeType.ntExpression, meta)
1595
+
1596
+ def postfix_expr(self, meta: Any, *children: Any) -> SyntaxNode:
1597
+ if not children:
1598
+ return self._make_node(SyntaxNodeType.ntExpression, meta)
1599
+ node = children[0]
1600
+ if not isinstance(node, SyntaxNode):
1601
+ node = self._ensure_expr_node(meta, node)
1602
+ for suffix in children[1:]:
1603
+ if isinstance(suffix, tuple) and suffix[0] == 'call':
1604
+ call_node = self._make_node(SyntaxNodeType.ntCall, meta)
1605
+ call_node.add_child(node)
1606
+ args = self._make_node(SyntaxNodeType.ntArguments, meta)
1607
+ call_args = suffix[1] if isinstance(suffix[1], list) else [suffix[1]]
1608
+ for arg in call_args:
1609
+ if isinstance(arg, SyntaxNode):
1610
+ args.add_child(arg)
1611
+ call_node.add_child(args)
1612
+ node = call_node
1613
+ elif isinstance(suffix, tuple) and suffix[0] == 'index':
1614
+ idx_node = self._make_node(SyntaxNodeType.ntIndexed, meta)
1615
+ idx_node.add_child(node)
1616
+ exprs = self._make_node(SyntaxNodeType.ntExpressions, meta)
1617
+ index_exprs = suffix[1] if isinstance(suffix[1], list) else [suffix[1]]
1618
+ for expr in index_exprs:
1619
+ if isinstance(expr, SyntaxNode):
1620
+ exprs.add_child(expr)
1621
+ idx_node.add_child(exprs)
1622
+ node = idx_node
1623
+ elif isinstance(suffix, tuple) and suffix[0] == 'field':
1624
+ dot_node = self._make_node(SyntaxNodeType.ntDot, meta)
1625
+ dot_node.add_child(node)
1626
+ name_node = self._make_expr_identifier(meta, suffix[1])
1627
+ dot_node.add_child(name_node)
1628
+ node = dot_node
1629
+ elif isinstance(suffix, tuple) and suffix[0] == 'deref':
1630
+ deref_node = self._make_node(SyntaxNodeType.ntDeref, meta)
1631
+ deref_node.add_child(node)
1632
+ node = deref_node
1633
+ return node
1634
+
1635
+ def call_suffix(self, meta: Any, *children: Any) -> tuple[str, list[SyntaxNode]]:
1636
+ args: list[SyntaxNode] = []
1637
+ for child in children:
1638
+ if isinstance(child, list):
1639
+ args.extend(child)
1640
+ return ('call', args)
1641
+
1642
+ def range_postfix(self, meta: Any, *children: Any) -> SyntaxNode:
1643
+ return self.postfix_expr(meta, *children)
1644
+
1645
+ def range_call_suffix(self, meta: Any, *children: Any) -> tuple[str, list[SyntaxNode]]:
1646
+ args: list[SyntaxNode] = []
1647
+ for child in children:
1648
+ if isinstance(child, list):
1649
+ args.extend(child)
1650
+ return ('call', args)
1651
+
1652
+ def range_arg_list(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1653
+ return [child for child in children if isinstance(child, SyntaxNode)]
1654
+
1655
+ def range_primary(self, meta: Any, child: Any) -> SyntaxNode:
1656
+ if isinstance(child, SyntaxNode):
1657
+ return child
1658
+ if self._is_text(child):
1659
+ parts = [self._make_expr_identifier(meta, part) for part in child.split('.')]
1660
+ return self.expr_qualified_name(meta, *parts)
1661
+ return self._ensure_expr_node(meta, child)
1662
+
1663
+ def op_add(self, meta: Any) -> str:
1664
+ return '+'
1665
+
1666
+ def op_sub(self, meta: Any) -> str:
1667
+ return '-'
1668
+
1669
+ def op_mul(self, meta: Any) -> str:
1670
+ return '*'
1671
+
1672
+ def op_fdiv(self, meta: Any) -> str:
1673
+ return '/'
1674
+
1675
+ def op_div(self, meta: Any, *_: Any) -> str:
1676
+ return 'DIV'
1677
+
1678
+ def op_mod(self, meta: Any, *_: Any) -> str:
1679
+ return 'MOD'
1680
+
1681
+ def op_shl(self, meta: Any, *_: Any) -> str:
1682
+ return 'SHL'
1683
+
1684
+ def op_shr(self, meta: Any, *_: Any) -> str:
1685
+ return 'SHR'
1686
+
1687
+ def index_suffix(self, meta: Any, exprs: list[SyntaxNode]) -> tuple[str, list[SyntaxNode]]:
1688
+ return ('index', exprs)
1689
+
1690
+ def field_suffix(self, meta: Any, name: Any) -> tuple[str, str]:
1691
+ return ('field', token_value(name))
1692
+
1693
+ def deref_suffix(self, meta: Any, *_: Any) -> tuple[str, None]:
1694
+ return ('deref', None)
1695
+
1696
+ def variable_ref(self, meta: Any, name: str) -> SyntaxNode:
1697
+ return self._make_expr_identifier(meta, name)
1698
+
1699
+ def assignment(self, meta: Any, *children: Any) -> SyntaxNode:
1700
+ nodes: list[SyntaxNode] = []
1701
+ for child in children:
1702
+ if isinstance(child, SyntaxNode):
1703
+ nodes.append(child)
1704
+ continue
1705
+ if is_token(child) and child.type == 'ASSIGN':
1706
+ continue
1707
+ nodes.append(self._ensure_expr_node(meta, child))
1708
+ left = nodes[0] if len(nodes) > 0 else self._make_node(SyntaxNodeType.ntExpression, meta)
1709
+ right = nodes[1] if len(nodes) > 1 else self._make_node(SyntaxNodeType.ntExpression, meta)
1710
+ node = self._make_node(SyntaxNodeType.ntAssign, meta)
1711
+ lhs = self._make_node(SyntaxNodeType.ntLHS, meta)
1712
+ rhs = self._make_node(SyntaxNodeType.ntRHS, meta)
1713
+ lhs.add_child(left)
1714
+ rhs.add_child(right)
1715
+ node.add_child(lhs)
1716
+ node.add_child(rhs)
1717
+ return node
1718
+
1719
+ def address_assignment(self, meta: Any, *children: Any) -> SyntaxNode:
1720
+ nodes: list[SyntaxNode] = []
1721
+ for child in children:
1722
+ if is_token(child) and child.type == 'ASSIGN':
1723
+ continue
1724
+ if isinstance(child, SyntaxNode):
1725
+ nodes.append(child)
1726
+ elif is_token(child) and child.type in {'NIL', 'TRUE', 'FALSE', 'SELF'}:
1727
+ nodes.append(self.primary(meta, child))
1728
+ elif child is not None:
1729
+ nodes.append(self._ensure_expr_node(meta, child))
1730
+ target = nodes[0] if nodes else self._make_node(SyntaxNodeType.ntExpression, meta)
1731
+ value = nodes[1] if len(nodes) > 1 else self._make_node(SyntaxNodeType.ntExpression, meta)
1732
+ addr = self._make_node(SyntaxNodeType.ntAddr, meta)
1733
+ addr.add_child(target)
1734
+ return self.assignment(meta, addr, value)
1735
+
1736
+ def call_expr(self, meta: Any, name: str, *children: Any) -> SyntaxNode:
1737
+ node = self._make_node(SyntaxNodeType.ntCall, meta)
1738
+ target = self._make_node(SyntaxNodeType.ntIdentifier, meta)
1739
+ target.set_attribute(AttributeName.anName, name)
1740
+ node.add_child(target)
1741
+ args = self._make_node(SyntaxNodeType.ntArguments, meta)
1742
+ for child in children:
1743
+ if isinstance(child, list):
1744
+ for arg in child:
1745
+ args.add_child(arg)
1746
+ node.add_child(args)
1747
+ return node
1748
+
1749
+ def call_statement(self, meta: Any, node: SyntaxNode) -> SyntaxNode:
1750
+ return node
1751
+
1752
+ def inline_number(self, meta: Any, token: Any) -> SyntaxNode:
1753
+ return self.literal(meta, token)
1754
+
1755
+ def inline_statement(self, meta: Any, *children: Any) -> SyntaxNode:
1756
+ node = self._make_node(SyntaxNodeType.ntUnknown, meta)
1757
+ node.set_attribute(AttributeName.anKind, 'inline')
1758
+ for child in children:
1759
+ if isinstance(child, SyntaxNode):
1760
+ node.add_child(child)
1761
+ return node
1762
+
1763
+ def inline_const_section(self, meta: Any, *children: Any) -> SyntaxNode:
1764
+ node = self._make_node(SyntaxNodeType.ntConstants, meta)
1765
+ node.set_attribute(AttributeName.anKind, 'inline')
1766
+ for child in children:
1767
+ if isinstance(child, SyntaxNode):
1768
+ node.add_child(child)
1769
+ return node
1770
+
1771
+ def inline_const_decl(self, meta: Any, *children: Any) -> SyntaxNode:
1772
+ return self.const_decl(meta, *children)
1773
+
1774
+ def inline_var_section(self, meta: Any, *children: Any) -> SyntaxNode:
1775
+ node = self._make_node(SyntaxNodeType.ntVariables, meta)
1776
+ node.set_attribute(AttributeName.anKind, 'inline')
1777
+ for child in children:
1778
+ if isinstance(child, list):
1779
+ for item in child:
1780
+ if isinstance(item, SyntaxNode):
1781
+ node.add_child(item)
1782
+ elif isinstance(child, SyntaxNode):
1783
+ node.add_child(child)
1784
+ return node
1785
+
1786
+ def inline_var_decl(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1787
+ names: list[str] = []
1788
+ type_node = None
1789
+ value_expr = None
1790
+ attributes: list[SyntaxNode] = []
1791
+ for child in children:
1792
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAttributes:
1793
+ attributes.append(child)
1794
+ elif isinstance(child, list):
1795
+ names = child
1796
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
1797
+ type_node = child
1798
+ elif isinstance(child, SyntaxNode):
1799
+ value_expr = child
1800
+ variables: list[SyntaxNode] = []
1801
+ for name in names:
1802
+ node = self._make_node(SyntaxNodeType.ntVariable, meta)
1803
+ node.add_child(self._make_valued(SyntaxNodeType.ntName, name, meta))
1804
+ if type_node is not None:
1805
+ node.add_child(type_node.clone())
1806
+ for attr in attributes:
1807
+ node.add_child(attr)
1808
+ if value_expr is not None:
1809
+ value_node = self._make_node(SyntaxNodeType.ntValue, meta)
1810
+ value_node.add_child(value_expr)
1811
+ node.add_child(value_node)
1812
+ variables.append(node)
1813
+ return variables
1814
+
1815
+ def argument(self, meta: Any, *children: Any) -> SyntaxNode:
1816
+ if children and (self._is_text(children[0]) or is_token(children[0])):
1817
+ name = token_value(children[0])
1818
+ expr = next((child for child in children[1:] if isinstance(child, SyntaxNode)), None)
1819
+ if expr is not None:
1820
+ node = self._make_node(SyntaxNodeType.ntNamedArgument, meta)
1821
+ node.set_attribute(AttributeName.anName, name)
1822
+ node.add_child(expr)
1823
+ return node
1824
+ node = self._make_node(SyntaxNodeType.ntPositionalArgument, meta)
1825
+ for child in children:
1826
+ if isinstance(child, SyntaxNode):
1827
+ node.add_child(child)
1828
+ return node
1829
+
1830
+ def formatted_argument(self, meta: Any, *children: Any) -> SyntaxNode:
1831
+ node = self._make_node(SyntaxNodeType.ntExpression, meta)
1832
+ node.set_attribute(AttributeName.anKind, 'format')
1833
+ for child in children:
1834
+ if isinstance(child, SyntaxNode):
1835
+ node.add_child(child)
1836
+ return node
1837
+
1838
+ def named_formatted_argument(self, meta: Any, name: Any, *children: Any) -> SyntaxNode:
1839
+ node = self._make_node(SyntaxNodeType.ntExpression, meta)
1840
+ node.set_attribute(AttributeName.anKind, 'format')
1841
+ node.add_child(self._make_expr_identifier(meta, token_value(name)))
1842
+ for child in children:
1843
+ if isinstance(child, SyntaxNode):
1844
+ node.add_child(child)
1845
+ return node
1846
+
1847
+ def statement_list(self, meta: Any, *children: Any) -> SyntaxNode:
1848
+ node = self._make_compound(SyntaxNodeType.ntStatements, meta)
1849
+ for child in children:
1850
+ if isinstance(child, SyntaxNode):
1851
+ node.add_child(child)
1852
+ elif isinstance(child, list):
1853
+ for item in child:
1854
+ if isinstance(item, SyntaxNode):
1855
+ node.add_child(item)
1856
+ return node
1857
+
1858
+ def compound_statement(self, meta: Any, *children: Any) -> SyntaxNode:
1859
+ node = self._make_compound(SyntaxNodeType.ntStatements, meta)
1860
+ for child in children:
1861
+ if isinstance(child, SyntaxNode):
1862
+ node.add_child(child)
1863
+ elif isinstance(child, list):
1864
+ for item in child:
1865
+ if isinstance(item, SyntaxNode):
1866
+ node.add_child(item)
1867
+ return node
1868
+
1869
+ def if_statement(self, meta: Any, *children: Any) -> SyntaxNode:
1870
+ node = self._make_node(SyntaxNodeType.ntIf, meta)
1871
+ for child in children:
1872
+ if isinstance(child, SyntaxNode):
1873
+ node.add_child(child)
1874
+ return node
1875
+
1876
+ def while_statement(self, meta: Any, *children: Any) -> SyntaxNode:
1877
+ node = self._make_node(SyntaxNodeType.ntWhile, meta)
1878
+ for child in children:
1879
+ if isinstance(child, SyntaxNode):
1880
+ node.add_child(child)
1881
+ return node
1882
+
1883
+ def for_statement(self, meta: Any, *children: Any) -> SyntaxNode:
1884
+ node = self._make_node(SyntaxNodeType.ntFor, meta)
1885
+ for child in children:
1886
+ if isinstance(child, SyntaxNode):
1887
+ node.add_child(child)
1888
+ return node
1889
+
1890
+ def for_init(self, meta: Any, *children: Any) -> SyntaxNode:
1891
+ name = None
1892
+ expr = None
1893
+ type_node = None
1894
+ is_var = any(is_token(child) and child.type == 'VAR' for child in children)
1895
+ for child in children:
1896
+ if self._is_text(child) or is_token(child):
1897
+ if is_token(child) and child.type == 'VAR':
1898
+ continue
1899
+ name = token_value(child)
1900
+ elif isinstance(child, SyntaxNode):
1901
+ if child.typ == SyntaxNodeType.ntType and type_node is None:
1902
+ type_node = child
1903
+ else:
1904
+ expr = child
1905
+ if is_var:
1906
+ node = self._make_node(SyntaxNodeType.ntVariable, meta)
1907
+ node.set_attribute(AttributeName.anKind, 'inline')
1908
+ if name is not None:
1909
+ node.add_child(self._make_valued(SyntaxNodeType.ntName, name, meta))
1910
+ if type_node is not None:
1911
+ node.add_child(type_node)
1912
+ if expr is not None:
1913
+ value_node = self._make_node(SyntaxNodeType.ntValue, meta)
1914
+ value_node.add_child(expr)
1915
+ node.add_child(value_node)
1916
+ return node
1917
+ assign = self._make_node(SyntaxNodeType.ntAssign, meta)
1918
+ lhs = self._make_node(SyntaxNodeType.ntLHS, meta)
1919
+ rhs = self._make_node(SyntaxNodeType.ntRHS, meta)
1920
+ if name is not None:
1921
+ ident = self._make_node(SyntaxNodeType.ntIdentifier, meta)
1922
+ ident.set_attribute(AttributeName.anName, name)
1923
+ lhs.add_child(ident)
1924
+ if expr is not None:
1925
+ rhs.add_child(expr)
1926
+ assign.add_child(lhs)
1927
+ assign.add_child(rhs)
1928
+ return assign
1929
+
1930
+ def for_in(self, meta: Any, *children: Any) -> SyntaxNode:
1931
+ name = None
1932
+ expr = None
1933
+ type_node = None
1934
+ is_var = any(is_token(child) and child.type == 'VAR' for child in children)
1935
+ for child in children:
1936
+ if self._is_text(child) or is_token(child):
1937
+ if is_token(child) and child.type == 'VAR':
1938
+ continue
1939
+ name = token_value(child)
1940
+ elif isinstance(child, SyntaxNode):
1941
+ if child.typ == SyntaxNodeType.ntType and type_node is None:
1942
+ type_node = child
1943
+ else:
1944
+ expr = child
1945
+ node = self._make_node(SyntaxNodeType.ntIn, meta)
1946
+ if is_var:
1947
+ var_node = self._make_node(SyntaxNodeType.ntVariable, meta)
1948
+ var_node.set_attribute(AttributeName.anKind, 'inline')
1949
+ if name is not None:
1950
+ var_node.add_child(self._make_valued(SyntaxNodeType.ntName, name, meta))
1951
+ if type_node is not None:
1952
+ var_node.add_child(type_node)
1953
+ node.add_child(var_node)
1954
+ elif name is not None:
1955
+ ident = self._make_node(SyntaxNodeType.ntIdentifier, meta)
1956
+ ident.set_attribute(AttributeName.anName, name)
1957
+ node.add_child(ident)
1958
+ if expr is not None:
1959
+ node.add_child(expr)
1960
+ return node
1961
+
1962
+ def repeat_statement(self, meta: Any, *children: Any) -> SyntaxNode:
1963
+ node = self._make_node(SyntaxNodeType.ntRepeat, meta)
1964
+ for child in children:
1965
+ if isinstance(child, SyntaxNode):
1966
+ node.add_child(child)
1967
+ return node
1968
+
1969
+ def case_statement(self, meta: Any, *children: Any) -> SyntaxNode:
1970
+ node = self._make_node(SyntaxNodeType.ntCase, meta)
1971
+ for child in self._flatten(children):
1972
+ if isinstance(child, SyntaxNode):
1973
+ node.add_child(child)
1974
+ return node
1975
+
1976
+ def case_selector_list(self, meta: Any, *children: Any) -> list[SyntaxNode]:
1977
+ return [child for child in self._flatten(children) if isinstance(child, SyntaxNode)]
1978
+
1979
+ def case_selector(self, meta: Any, *children: Any) -> SyntaxNode:
1980
+ node = self._make_node(SyntaxNodeType.ntCaseSelector, meta)
1981
+ for child in children:
1982
+ if isinstance(child, SyntaxNode):
1983
+ node.add_child(child)
1984
+ return node
1985
+
1986
+ def case_label_list(self, meta: Any, *children: Any) -> SyntaxNode:
1987
+ node = self._make_node(SyntaxNodeType.ntCaseLabels, meta)
1988
+ for child in children:
1989
+ if isinstance(child, SyntaxNode):
1990
+ node.add_child(child)
1991
+ return node
1992
+
1993
+ def case_label(self, meta: Any, *children: Any) -> SyntaxNode:
1994
+ node = self._make_node(SyntaxNodeType.ntCaseLabel, meta)
1995
+ for child in children:
1996
+ if isinstance(child, SyntaxNode):
1997
+ node.add_child(child)
1998
+ return node
1999
+
2000
+ def case_else(self, meta: Any, *children: Any) -> SyntaxNode:
2001
+ node = self._make_node(SyntaxNodeType.ntCaseElse, meta)
2002
+ for child in children:
2003
+ if isinstance(child, SyntaxNode):
2004
+ node.add_child(child)
2005
+ return node
2006
+
2007
+ def with_statement(self, meta: Any, *children: Any) -> SyntaxNode:
2008
+ node = self._make_node(SyntaxNodeType.ntWith, meta)
2009
+ exprs: list[SyntaxNode] = []
2010
+ statements: list[SyntaxNode] = []
2011
+ for child in children:
2012
+ if isinstance(child, list):
2013
+ for item in child:
2014
+ if isinstance(item, SyntaxNode):
2015
+ exprs.append(item)
2016
+ elif isinstance(child, SyntaxNode):
2017
+ statements.append(child)
2018
+ if statements and not exprs:
2019
+ exprs = statements[:-1]
2020
+ statements = statements[-1:]
2021
+ for stmt in statements:
2022
+ node.add_child(stmt)
2023
+ if exprs:
2024
+ exprs_node = self._make_node(SyntaxNodeType.ntExpressions, meta)
2025
+ for expr in exprs:
2026
+ exprs_node.add_child(expr)
2027
+ node.add_child(exprs_node)
2028
+ return node
2029
+
2030
+ def try_statement(self, meta: Any, *children: Any) -> SyntaxNode:
2031
+ node = self._make_node(SyntaxNodeType.ntTry, meta)
2032
+ for child in children:
2033
+ if isinstance(child, SyntaxNode):
2034
+ node.add_child(child)
2035
+ return node
2036
+
2037
+ def except_block(self, meta: Any, *children: Any) -> SyntaxNode:
2038
+ node = self._make_node(SyntaxNodeType.ntExcept, meta)
2039
+ for child in children:
2040
+ if isinstance(child, SyntaxNode):
2041
+ node.add_child(child)
2042
+ return node
2043
+
2044
+ def exception_handler(self, meta: Any, *children: Any) -> SyntaxNode:
2045
+ node = self._make_node(SyntaxNodeType.ntExceptionHandler, meta)
2046
+ for child in children:
2047
+ if isinstance(child, SyntaxNode):
2048
+ node.add_child(child)
2049
+ return node
2050
+
2051
+ def finally_block(self, meta: Any, *children: Any) -> SyntaxNode:
2052
+ node = self._make_node(SyntaxNodeType.ntFinally, meta)
2053
+ for child in children:
2054
+ if isinstance(child, SyntaxNode):
2055
+ node.add_child(child)
2056
+ return node
2057
+
2058
+ def raise_statement(self, meta: Any, *children: Any) -> SyntaxNode:
2059
+ node = self._make_node(SyntaxNodeType.ntRaise, meta)
2060
+ for child in children:
2061
+ if isinstance(child, SyntaxNode):
2062
+ node.add_child(child)
2063
+ return node
2064
+
2065
+ def goto_statement(self, meta: Any, *children: Any) -> SyntaxNode:
2066
+ node = self._make_node(SyntaxNodeType.ntGoto, meta)
2067
+ for child in children:
2068
+ if isinstance(child, SyntaxNode):
2069
+ node.add_child(child)
2070
+ elif self._is_text(child):
2071
+ node.set_attribute(AttributeName.anName, child)
2072
+ return node
2073
+
2074
+ def label_statement(self, meta: Any, *children: Any) -> SyntaxNode:
2075
+ node = self._make_node(SyntaxNodeType.ntStatement, meta)
2076
+ node.set_attribute(AttributeName.anKind, 'label')
2077
+ for child in children:
2078
+ if isinstance(child, SyntaxNode):
2079
+ node.add_child(child)
2080
+ elif self._is_text(child):
2081
+ name_node = self._make_node(SyntaxNodeType.ntLabel, meta)
2082
+ name_node.set_attribute(AttributeName.anName, child)
2083
+ node.add_child(name_node)
2084
+ return node
2085
+
2086
+ def inherited_statement(self, meta: Any, *children: Any) -> SyntaxNode:
2087
+ node = self._make_node(SyntaxNodeType.ntInherited, meta)
2088
+ for child in children:
2089
+ if isinstance(child, SyntaxNode):
2090
+ node.add_child(child)
2091
+ return node
2092
+
2093
+ def inherited_expr(self, meta: Any, *children: Any) -> SyntaxNode:
2094
+ return self.inherited_statement(meta, *children)
2095
+
2096
+ def break_statement(self, meta: Any, *_: Any) -> SyntaxNode:
2097
+ node = self._make_node(SyntaxNodeType.ntStatement, meta)
2098
+ node.set_attribute(AttributeName.anKind, 'break')
2099
+ return node
2100
+
2101
+ def continue_statement(self, meta: Any, *_: Any) -> SyntaxNode:
2102
+ node = self._make_node(SyntaxNodeType.ntStatement, meta)
2103
+ node.set_attribute(AttributeName.anKind, 'continue')
2104
+ return node
2105
+
2106
+ def exit_statement(self, meta: Any, *children: Any) -> SyntaxNode:
2107
+ node = self._make_node(SyntaxNodeType.ntStatement, meta)
2108
+ node.set_attribute(AttributeName.anKind, 'exit')
2109
+ for child in children:
2110
+ if isinstance(child, SyntaxNode):
2111
+ node.add_child(child)
2112
+ return node
2113
+
2114
+ def asm_statement(self, meta: Any, *children: Any) -> SyntaxNode:
2115
+ node = self._make_compound(SyntaxNodeType.ntStatements, meta)
2116
+ node.set_attribute(AttributeName.anType, 'asm')
2117
+ return node
2118
+
2119
+ def empty_statement(self, meta: Any) -> SyntaxNode:
2120
+ return self._make_node(SyntaxNodeType.ntEmptyStatement, meta)
2121
+
2122
+ def requires_clause(self, meta: Any, *children: Any) -> SyntaxNode:
2123
+ node = self._make_node(SyntaxNodeType.ntRequires, meta)
2124
+ for child in children:
2125
+ if isinstance(child, SyntaxNode):
2126
+ node.add_child(child)
2127
+ elif self._is_text(child):
2128
+ pkg = self._make_node(SyntaxNodeType.ntPackage, meta)
2129
+ pkg.set_attribute(AttributeName.anName, child)
2130
+ node.add_child(pkg)
2131
+ return node
2132
+
2133
+ def contains_clause(self, meta: Any, *children: Any) -> SyntaxNode:
2134
+ node = self._make_node(SyntaxNodeType.ntContains, meta)
2135
+ for child in children:
2136
+ if isinstance(child, SyntaxNode):
2137
+ node.add_child(child)
2138
+ return node
2139
+
2140
+ def contains_item(self, meta: Any, *children: Any) -> SyntaxNode:
2141
+ return self.uses_item(meta, *children)
2142
+
2143
+ def exports_section(self, meta: Any, *children: Any) -> SyntaxNode:
2144
+ node = self._make_node(SyntaxNodeType.ntExports, meta)
2145
+ for child in children:
2146
+ if isinstance(child, SyntaxNode):
2147
+ node.add_child(child)
2148
+ return node
2149
+
2150
+ def exports_item(self, meta: Any, *children: Any) -> SyntaxNode:
2151
+ node = self._make_node(SyntaxNodeType.ntElement, meta)
2152
+ for child in children:
2153
+ if isinstance(child, SyntaxNode):
2154
+ node.add_child(child)
2155
+ elif self._is_text(child):
2156
+ name_node = self._make_node(SyntaxNodeType.ntName, meta)
2157
+ name_node.set_attribute(AttributeName.anName, child)
2158
+ node.add_child(name_node)
2159
+ return node
2160
+
2161
+ def exports_specifier(self, meta: Any, *children: Any) -> SyntaxNode:
2162
+ node = self._make_node(SyntaxNodeType.ntUnknown, meta)
2163
+ for child in children:
2164
+ if isinstance(child, SyntaxNode):
2165
+ node.add_child(child)
2166
+ return node
2167
+
2168
+ def attribute_sections(self, meta: Any, *children: Any) -> SyntaxNode:
2169
+ node = self._make_node(SyntaxNodeType.ntAttributes, meta)
2170
+ for child in children:
2171
+ if isinstance(child, list):
2172
+ for item in child:
2173
+ if isinstance(item, SyntaxNode):
2174
+ node.add_child(item)
2175
+ elif isinstance(child, SyntaxNode):
2176
+ node.add_child(child)
2177
+ return node
2178
+
2179
+ def attribute_section(self, meta: Any, *children: Any) -> list[SyntaxNode]:
2180
+ return [child for child in children if isinstance(child, SyntaxNode)]
2181
+
2182
+ def attribute_name(self, meta: Any, *children: Any) -> str:
2183
+ for child in children:
2184
+ if self._is_text(child) or is_token(child):
2185
+ return token_value(child)
2186
+ return ''
2187
+
2188
+ def attribute_keyword(self, meta: Any, token: Any) -> str:
2189
+ return token_value(token)
2190
+
2191
+ def attribute(self, meta: Any, *children: Any) -> SyntaxNode:
2192
+ name = None
2193
+ args = None
2194
+ for child in children:
2195
+ if self._is_text(child) or is_token(child):
2196
+ name = token_value(child)
2197
+ elif isinstance(child, SyntaxNode):
2198
+ args = child
2199
+ node = self._make_node(SyntaxNodeType.ntAttribute, meta)
2200
+ if name is not None:
2201
+ node.set_attribute(AttributeName.anName, name)
2202
+ if args is not None:
2203
+ node.add_child(args)
2204
+ return node
2205
+
2206
+ def attribute_arguments(self, meta: Any, *children: Any) -> SyntaxNode:
2207
+ node = self._make_node(SyntaxNodeType.ntArguments, meta)
2208
+ for child in children:
2209
+ if isinstance(child, list):
2210
+ for arg in child:
2211
+ if isinstance(arg, SyntaxNode):
2212
+ node.add_child(arg)
2213
+ return node
2214
+
2215
+ def set_const(self, meta: Any, *children: Any) -> SyntaxNode:
2216
+ node = self._make_node(SyntaxNodeType.ntSet, meta)
2217
+ for child in children:
2218
+ if isinstance(child, list):
2219
+ for item in child:
2220
+ if isinstance(item, SyntaxNode):
2221
+ node.add_child(item)
2222
+ elif isinstance(child, SyntaxNode):
2223
+ node.add_child(child)
2224
+ return node
2225
+
2226
+ def set_element_list(self, meta: Any, *children: Any) -> list[SyntaxNode]:
2227
+ return [child for child in self._flatten(children) if isinstance(child, SyntaxNode)]
2228
+
2229
+ def set_element(self, meta: Any, *children: Any) -> SyntaxNode:
2230
+ nodes = [child for child in children if isinstance(child, SyntaxNode)]
2231
+ if len(nodes) == 2:
2232
+ subrange = self._make_node(SyntaxNodeType.ntSubrange, meta)
2233
+ subrange.add_child(nodes[0])
2234
+ subrange.add_child(nodes[1])
2235
+ return subrange
2236
+ if nodes:
2237
+ return nodes[0]
2238
+ return self._make_node(SyntaxNodeType.ntExpression, meta)
2239
+
2240
+ def array_const(self, meta: Any, *children: Any) -> SyntaxNode:
2241
+ node = self._make_node(SyntaxNodeType.ntExpressions, meta)
2242
+ for child in children:
2243
+ for item in self._flatten(child):
2244
+ if isinstance(item, SyntaxNode):
2245
+ node.add_child(item)
2246
+ return node
2247
+
2248
+ def const_value_list(self, meta: Any, *children: Any) -> list[SyntaxNode]:
2249
+ return [child for child in children if isinstance(child, SyntaxNode)]
2250
+
2251
+ def record_const(self, meta: Any, *children: Any) -> SyntaxNode:
2252
+ node = self._make_node(SyntaxNodeType.ntUnknown, meta)
2253
+ for child in children:
2254
+ if isinstance(child, SyntaxNode):
2255
+ node.add_child(child)
2256
+ return node
2257
+
2258
+ def record_const_item(self, meta: Any, *children: Any) -> SyntaxNode:
2259
+ node = self._make_node(SyntaxNodeType.ntValue, meta)
2260
+ for child in children:
2261
+ if isinstance(child, SyntaxNode):
2262
+ node.add_child(child)
2263
+ return node
2264
+
2265
+ def _build_routine(
2266
+ self,
2267
+ meta: Any,
2268
+ name: str,
2269
+ kind: str,
2270
+ return_type: SyntaxNode | None,
2271
+ children: Iterable[Any],
2272
+ ) -> SyntaxNode:
2273
+ node = self._make_compound(SyntaxNodeType.ntMethod, meta)
2274
+ node.set_attribute(AttributeName.anName, name)
2275
+ node.set_attribute(AttributeName.anKind, kind)
2276
+
2277
+ parameters = None
2278
+ directives = None
2279
+ body: Any = None
2280
+ for child in children:
2281
+ if isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntParameters:
2282
+ parameters = child
2283
+ elif isinstance(child, dict):
2284
+ directives = child
2285
+ elif isinstance(child, SyntaxNode) or isinstance(child, list):
2286
+ body = child
2287
+
2288
+ if parameters is not None:
2289
+ node.add_child(parameters)
2290
+ if return_type is not None:
2291
+ return_node = self._make_node(SyntaxNodeType.ntReturnType, meta)
2292
+ return_node.add_child(return_type)
2293
+ node.add_child(return_node)
2294
+ if directives:
2295
+ self._apply_directives(node, directives)
2296
+ if body is not None:
2297
+ if isinstance(body, list):
2298
+ for item in body:
2299
+ if isinstance(item, SyntaxNode):
2300
+ node.add_child(item)
2301
+ elif isinstance(body, SyntaxNode):
2302
+ node.add_child(body)
2303
+ return node
2304
+
2305
+ def _apply_directives(self, node: SyntaxNode, directives: dict[str, str]) -> None:
2306
+ for key, value in directives.items():
2307
+ attr = {
2308
+ 'methodbinding': AttributeName.anMethodBinding,
2309
+ 'reintroduce': AttributeName.anReintroduce,
2310
+ 'overload': AttributeName.anOverload,
2311
+ 'abstract': AttributeName.anAbstract,
2312
+ 'inline': AttributeName.anInline,
2313
+ 'callingconvention': AttributeName.anCallingConvention,
2314
+ 'forwarded': AttributeName.anForwarded,
2315
+ 'external': AttributeName.anExternal,
2316
+ 'deprecated': AttributeName.anDeprecated,
2317
+ 'static': AttributeName.anStatic,
2318
+ 'final': AttributeName.anFinal,
2319
+ 'sealed': AttributeName.anSealed,
2320
+ 'assembler': AttributeName.anAssembler,
2321
+ 'unsafe': AttributeName.anUnsafe,
2322
+ 'export': AttributeName.anExport,
2323
+ 'far': AttributeName.anFar,
2324
+ 'near': AttributeName.anNear,
2325
+ 'noreturn': AttributeName.anNoReturn,
2326
+ 'varargs': AttributeName.anVarArgs,
2327
+ }.get(key)
2328
+ if attr is not None:
2329
+ node.set_attribute(attr, value)
2330
+
2331
+ def _apply_decl_directives(self, node: SyntaxNode, directives: dict[str, str]) -> None:
2332
+ for key, value in directives.items():
2333
+ attr = {
2334
+ 'deprecated': AttributeName.anDeprecated,
2335
+ 'platform': AttributeName.anKind,
2336
+ 'experimental': AttributeName.anKind,
2337
+ 'library': AttributeName.anKind,
2338
+ }.get(key)
2339
+ if attr is None:
2340
+ continue
2341
+ if attr == AttributeName.anKind and value == 'true':
2342
+ node.set_attribute(attr, key)
2343
+ else:
2344
+ node.set_attribute(attr, value)
2345
+
2346
+ def _build_routine_from_children(
2347
+ self,
2348
+ meta: Any,
2349
+ kind: str,
2350
+ children: Iterable[Any],
2351
+ ) -> SyntaxNode:
2352
+ name = None
2353
+ params = None
2354
+ return_type = None
2355
+ type_params = None
2356
+ directives = None
2357
+ body = None
2358
+ attributes: list[SyntaxNode] = []
2359
+ is_class = False
2360
+ forwarded = False
2361
+ for child in children:
2362
+ if is_token(child) and child.type == 'CLASS':
2363
+ is_class = True
2364
+ elif is_token(child) and child.type == 'FORWARD':
2365
+ forwarded = True
2366
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntAttributes:
2367
+ attributes.append(child)
2368
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntTypeParams:
2369
+ type_params = child
2370
+ elif self._is_text(child):
2371
+ name = child
2372
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntParameters:
2373
+ params = child
2374
+ elif isinstance(child, SyntaxNode) and child.typ == SyntaxNodeType.ntType:
2375
+ return_type = child
2376
+ elif isinstance(child, dict):
2377
+ directives = child
2378
+ elif isinstance(child, SyntaxNode) or isinstance(child, list):
2379
+ body = child
2380
+ if name is None:
2381
+ name = kind
2382
+ if isinstance(name, str) and '<' in name:
2383
+ base_name, generic_args = self._split_generic_name(name)
2384
+ name = base_name
2385
+ if type_params is None and generic_args:
2386
+ type_params = self._type_params_from_generic_name(meta, generic_args)
2387
+ routine = self._build_routine(meta, name, kind, return_type, [params, directives, body])
2388
+ if is_class:
2389
+ routine.set_attribute(AttributeName.anClass, 'true')
2390
+ if forwarded:
2391
+ routine.set_attribute(AttributeName.anForwarded, 'true')
2392
+ for attr in attributes:
2393
+ routine.add_child(attr)
2394
+ if type_params is not None:
2395
+ routine.add_child(type_params)
2396
+ return routine
2397
+
2398
+ def _expr_to_text(self, node: SyntaxNode) -> str:
2399
+ if isinstance(node, ValuedSyntaxNode):
2400
+ return node.value
2401
+ name = node.get_attribute(AttributeName.anName)
2402
+ if name:
2403
+ return name
2404
+ return ''
2405
+
2406
+ def _split_generic_name(self, name: str) -> tuple[str, str]:
2407
+ if '<' in name:
2408
+ base, rest = name.split('<', 1)
2409
+ return base, f'<{rest}'
2410
+ return name, ''
2411
+
2412
+ def _type_params_from_generic_name(self, meta: Any, generic_args: str) -> SyntaxNode | None:
2413
+ if not generic_args.startswith('<') or not generic_args.endswith('>'):
2414
+ return None
2415
+ inner = generic_args[1:-1].strip()
2416
+ if not inner:
2417
+ return None
2418
+ parsed: list[dict[str, Any]] = []
2419
+ current_group_indices: list[int] = []
2420
+ for segment in self._split_top_level(inner, ';'):
2421
+ if not segment:
2422
+ continue
2423
+ left, right = self._split_first_top_level(segment, ':')
2424
+ if right:
2425
+ names = [part for part in self._split_top_level(left, ',') if part]
2426
+ constraints = [part for part in self._split_top_level(right, ',') if part]
2427
+ current_group_indices = []
2428
+ for name in names:
2429
+ entry = {'name': name, 'constraints': list(constraints)}
2430
+ parsed.append(entry)
2431
+ current_group_indices.append(len(parsed) - 1)
2432
+ continue
2433
+
2434
+ parts = [part for part in self._split_top_level(segment, ',') if part]
2435
+ if not parts:
2436
+ continue
2437
+ if parsed and all(self._looks_like_constraint_fragment(part) for part in parts):
2438
+ targets = current_group_indices if current_group_indices else [len(parsed) - 1]
2439
+ for index in targets:
2440
+ parsed[index]['constraints'].extend(parts)
2441
+ continue
2442
+
2443
+ current_group_indices = []
2444
+ for part in parts:
2445
+ parsed.append({'name': part, 'constraints': []})
2446
+ current_group_indices.append(len(parsed) - 1)
2447
+
2448
+ if not parsed:
2449
+ return None
2450
+ params = self._make_node(SyntaxNodeType.ntTypeParams, meta)
2451
+ for item in parsed:
2452
+ raw_name = item['name']
2453
+ type_param = self._make_node(SyntaxNodeType.ntTypeParam, meta)
2454
+ type_param.add_child(self._make_valued(SyntaxNodeType.ntName, raw_name, meta))
2455
+ constraints = item.get('constraints') or []
2456
+ if constraints:
2457
+ constraints_node = self._make_node(SyntaxNodeType.ntConstraints, meta)
2458
+ for constraint_text in constraints:
2459
+ constraints_node.add_child(self._constraint_node_from_text(meta, constraint_text))
2460
+ type_param.add_child(constraints_node)
2461
+ params.add_child(type_param)
2462
+ return params
2463
+
2464
+ def _split_first_top_level(self, text: str, delimiter: str) -> tuple[str, str]:
2465
+ angle = 0
2466
+ square = 0
2467
+ round_ = 0
2468
+ in_string = False
2469
+ i = 0
2470
+ while i < len(text):
2471
+ ch = text[i]
2472
+ if ch == "'":
2473
+ if in_string and i + 1 < len(text) and text[i + 1] == "'":
2474
+ i += 2
2475
+ continue
2476
+ in_string = not in_string
2477
+ i += 1
2478
+ continue
2479
+ if in_string:
2480
+ i += 1
2481
+ continue
2482
+ if ch == '<':
2483
+ angle += 1
2484
+ elif ch == '>':
2485
+ angle = max(0, angle - 1)
2486
+ elif ch == '[':
2487
+ square += 1
2488
+ elif ch == ']':
2489
+ square = max(0, square - 1)
2490
+ elif ch == '(':
2491
+ round_ += 1
2492
+ elif ch == ')':
2493
+ round_ = max(0, round_ - 1)
2494
+ elif ch == delimiter and angle == 0 and square == 0 and round_ == 0:
2495
+ return (text[:i].strip(), text[i + 1 :].strip())
2496
+ i += 1
2497
+ return (text.strip(), '')
2498
+
2499
+ def _split_top_level(self, text: str, delimiter: str) -> list[str]:
2500
+ parts: list[str] = []
2501
+ current: list[str] = []
2502
+ angle = 0
2503
+ square = 0
2504
+ round_ = 0
2505
+ in_string = False
2506
+ i = 0
2507
+ while i < len(text):
2508
+ ch = text[i]
2509
+ if ch == "'":
2510
+ current.append(ch)
2511
+ if in_string and i + 1 < len(text) and text[i + 1] == "'":
2512
+ current.append(text[i + 1])
2513
+ i += 2
2514
+ continue
2515
+ in_string = not in_string
2516
+ i += 1
2517
+ continue
2518
+ if not in_string:
2519
+ if ch == '<':
2520
+ angle += 1
2521
+ elif ch == '>':
2522
+ angle = max(0, angle - 1)
2523
+ elif ch == '[':
2524
+ square += 1
2525
+ elif ch == ']':
2526
+ square = max(0, square - 1)
2527
+ elif ch == '(':
2528
+ round_ += 1
2529
+ elif ch == ')':
2530
+ round_ = max(0, round_ - 1)
2531
+ elif ch == delimiter and angle == 0 and square == 0 and round_ == 0:
2532
+ part = ''.join(current).strip()
2533
+ if part:
2534
+ parts.append(part)
2535
+ current = []
2536
+ i += 1
2537
+ continue
2538
+ current.append(ch)
2539
+ i += 1
2540
+ part = ''.join(current).strip()
2541
+ if part:
2542
+ parts.append(part)
2543
+ return parts
2544
+
2545
+ def _looks_like_constraint_fragment(self, fragment: str) -> bool:
2546
+ token = fragment.strip().casefold()
2547
+ return token in {'class', 'record', 'constructor', 'interface', 'unmanaged'}
2548
+
2549
+ def _constraint_node_from_text(self, meta: Any, constraint_text: str) -> SyntaxNode:
2550
+ text = constraint_text.strip()
2551
+ lowered = text.casefold()
2552
+ if lowered == 'class':
2553
+ return self._make_node(SyntaxNodeType.ntClassConstraint, meta)
2554
+ if lowered == 'record':
2555
+ return self._make_node(SyntaxNodeType.ntRecordConstraint, meta)
2556
+ if lowered == 'constructor':
2557
+ return self._make_node(SyntaxNodeType.ntConstructorConstraint, meta)
2558
+ if lowered == 'interface':
2559
+ return self._make_node(SyntaxNodeType.ntInterfaceConstraint, meta)
2560
+ if lowered == 'unmanaged':
2561
+ return self._make_node(SyntaxNodeType.ntUnmanagedConstraint, meta)
2562
+ node = self._make_node(SyntaxNodeType.ntType, meta)
2563
+ node.set_attribute(AttributeName.anName, text)
2564
+ return node
2565
+
2566
+ def _dequote_string(self, value: str) -> str:
2567
+ if len(value) < 2:
2568
+ return value
2569
+ if value[0] != "'":
2570
+ return value
2571
+ if value[-1] == "'":
2572
+ inner = value[1:-1]
2573
+ else:
2574
+ inner = value[1:]
2575
+ return inner.replace("''", "'")
2576
+
2577
+ def _make_node(self, typ: SyntaxNodeType, meta: Any) -> SyntaxNode:
2578
+ node = SyntaxNode(typ)
2579
+ self._set_pos(node, meta)
2580
+ return node
2581
+
2582
+ def _make_compound(self, typ: SyntaxNodeType, meta: Any) -> CompoundSyntaxNode:
2583
+ node = CompoundSyntaxNode(typ)
2584
+ self._set_pos(node, meta)
2585
+ return node
2586
+
2587
+ def _make_valued(self, typ: SyntaxNodeType, value: str, meta: Any) -> ValuedSyntaxNode:
2588
+ node = ValuedSyntaxNode(typ)
2589
+ node.value = value
2590
+ self._set_pos(node, meta)
2591
+ return node
2592
+
2593
+ def _set_pos(self, node: SyntaxNode, meta: Any) -> None:
2594
+ if meta is None:
2595
+ return
2596
+ if getattr(meta, 'line', None) is not None:
2597
+ node.line = meta.line
2598
+ node.col = meta.column
2599
+ node.file_name = self.file_name
2600
+ if getattr(meta, 'end_line', None) is not None:
2601
+ node.token_end_line = meta.end_line
2602
+ node.token_end_col = meta.end_column
2603
+ if isinstance(node, CompoundSyntaxNode):
2604
+ node.end_line = meta.end_line
2605
+ node.end_col = meta.end_column
2606
+
2607
+ def _binary_chain(self, meta: Any, children: Any, mapping: dict[str, SyntaxNodeType]) -> SyntaxNode:
2608
+ items = list(children)
2609
+ if not items:
2610
+ return self._make_node(SyntaxNodeType.ntExpression, meta)
2611
+ node = items[0] if isinstance(items[0], SyntaxNode) else self._make_node(SyntaxNodeType.ntExpression, meta)
2612
+ idx = 1
2613
+ while idx < len(items):
2614
+ op = items[idx]
2615
+ rhs = items[idx + 1] if idx + 1 < len(items) else None
2616
+ op_key = op.value if is_token(op) else str(op)
2617
+ op_key = op_key.upper()
2618
+ op_type = mapping.get(op_key) or mapping.get(op_key.lower()) or mapping.get(op_key)
2619
+ if rhs is None or op_type is None or not isinstance(rhs, SyntaxNode):
2620
+ break
2621
+ op_node = self._make_node(op_type, meta)
2622
+ op_node.add_child(node)
2623
+ op_node.add_child(rhs)
2624
+ node = op_node
2625
+ idx += 2
2626
+ return node
2627
+
2628
+ def _ensure_expr_node(self, meta: Any, value: Any) -> SyntaxNode:
2629
+ if isinstance(value, SyntaxNode):
2630
+ return value
2631
+ name = token_value(value)
2632
+ return self._make_expr_identifier(meta, name)
2633
+
2634
+ def _make_expr_identifier(self, meta: Any, name: str) -> SyntaxNode:
2635
+ base, generic_args = self._split_generic_name(name)
2636
+ node = self._make_node(SyntaxNodeType.ntIdentifier, meta)
2637
+ node.set_attribute(AttributeName.anName, base)
2638
+ if generic_args:
2639
+ node.set_attribute(AttributeName.anGenericArgs, generic_args)
2640
+ return node
2641
+
2642
+ def _flatten(self, value: Any) -> Iterable[Any]:
2643
+ if isinstance(value, (list, tuple)):
2644
+ for item in value:
2645
+ yield from self._flatten(item)
2646
+ else:
2647
+ yield value
2648
+
2649
+ def _is_text(self, value: Any) -> bool:
2650
+ return isinstance(value, str) and not is_token(value)
2651
+
2652
+ def _proc_type_directive_attrs(self, values: Iterable[str]) -> dict[str, str]:
2653
+ attrs: dict[str, str] = {}
2654
+ for value in values:
2655
+ if value == 'winapi':
2656
+ attrs['callingconvention'] = 'winapi'
2657
+ elif value in {'cdecl', 'stdcall', 'pascal', 'register', 'safecall'}:
2658
+ attrs['callingconvention'] = value
2659
+ elif value == 'varargs':
2660
+ attrs['varargs'] = 'true'
2661
+ return attrs
2662
+
2663
+ def _extract_name(self, children: Iterable[Any], default: str) -> str:
2664
+ for child in self._flatten(children):
2665
+ if self._is_text(child):
2666
+ return child
2667
+ return default
2668
+
2669
+ def _build_program_root(self, meta: Any, kind: str, children: Iterable[Any]) -> SyntaxNode:
2670
+ name = self._extract_name(children, default=kind)
2671
+ root = self._make_node(SyntaxNodeType.ntUnit, meta)
2672
+ root.set_attribute(AttributeName.anName, name)
2673
+ root.set_attribute(AttributeName.anKind, kind)
2674
+ for child in children:
2675
+ if isinstance(child, SyntaxNode):
2676
+ root.add_child(child)
2677
+ elif isinstance(child, list):
2678
+ for item in child:
2679
+ if isinstance(item, SyntaxNode):
2680
+ root.add_child(item)
2681
+ return root
2682
+
2683
+ builder = Builder()
2684
+ return builder.transform(tree)