Coverage for src/lumen/fhirpath/parser/ASTPathListener.py: 100%
33 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-08-31 18:46 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-08-31 18:46 +0000
1from antlr4.tree.Tree import TerminalNodeImpl
2from lumen.fhirpath.parser.generated.FHIRPathListener import FHIRPathListener
5def has_node_type_text(node_type):
6 # In general we need mostly terminal nodes (e.g. Identifier and any Literal)
7 # But the code also uses TypeSpecifier, InvocationExpression and TermExpression
8 return node_type.endswith("Literal") or node_type in [
9 "LiteralTerm",
10 "Identifier",
11 "TypeSpecifier",
12 "InvocationExpression",
13 "TermExpression",
14 ]
17class ASTPathListener(FHIRPathListener):
18 def __init__(self):
19 self.parentStack = [{}]
21 def pushNode(self, nodeType, ctx):
22 parentNode = self.parentStack[-1]
23 node = {"type": nodeType, "terminalNodeText": []}
24 if has_node_type_text(nodeType):
25 node["text"] = ctx.getText()
26 for child in ctx.children:
27 if isinstance(child, TerminalNodeImpl):
28 node["terminalNodeText"].append(child.getText())
30 if "children" not in parentNode:
31 parentNode["children"] = []
33 parentNode["children"].append(node)
35 self.parentStack.append(node)
37 def popNode(self):
38 if len(self.parentStack) > 0:
39 self.parentStack.pop()
41 def __getattribute__(self, name):
42 attr = object.__getattribute__(self, name)
44 if name in FHIRPathListener.__dict__ and callable(attr):
46 def newfunc(*args, **kwargs):
47 if name.startswith("enter"):
48 self.pushNode(name[5:], args[0])
50 if name.startswith("exit"):
51 self.popNode()
53 return attr(*args, **kwargs)
55 return newfunc
56 return attr