diff --git a/pytai/model.py b/pytai/model.py
index e2103dd..be0469d 100644
--- a/pytai/model.py
+++ b/pytai/model.py
@@ -34,6 +34,19 @@
from .common import *
from . import utils
+class PytaiUnparsedAccessException(Exception):
+ """The parser tried to access an element that hasn't been parsed yet.
+
+ This can happen when the file format defines cross-references between
+ structures, i.e. one structure contains an element that isn't relative to
+ itself, but to another structure.
+
+ Upon catching such an exception, the caller can choose to raise a flag
+ and continue parsing the file. After proceeding with the parsing until the end,
+ the caller can restart the parsing (if the flag is raised) in hope that that
+ the cross reference has been resolved (i.e. the referenced element has been parsed).
+ The caller should set a limit to the amount of reparse attempts.
+ """
class Parser(object):
ChildAttr = namedtuple("ParserChildAttr", "name value start_offset end_offset is_metavar is_array")
@@ -226,6 +239,8 @@ def _get_details(self, debug_dict: Dict[str, Dict[str, int]], parent: "KaitaiStr
is_array = True
except KeyError:
pass
+ except AttributeError:
+ raise PytaiUnparsedAccessException(f"Unparsed access during parsing of '{child_name}' ")
return start_offset, end_offset, is_array, value
diff --git a/pytai/tests/kaitai_to_xml.py b/pytai/tests/kaitai_to_xml.py
index 3bcfcaa..90f1e67 100644
--- a/pytai/tests/kaitai_to_xml.py
+++ b/pytai/tests/kaitai_to_xml.py
@@ -52,8 +52,7 @@ def kaitai_to_xml(parser: "KaitaiParser", path: str) -> ET.ElementTree:
XML representation of the file structure.
"""
-
- root = ET.Element("root")
+ reparse_needed = False
def recurse(parent_object: Union[List["KaitaiStruct"], "KaitaiStruct"], parent_node: ET.Element, is_array: bool) -> None:
"""Recursive function to built the XML tree.
@@ -70,26 +69,36 @@ def recurse(parent_object: Union[List["KaitaiStruct"], "KaitaiStruct"], parent_n
True if parent_object is a list, false otherwise.
"""
- if is_array:
- values = parent_object
- else:
- values = parser.get_children(parent_object)
-
- for child_attr in values:
-
-
- current_node = ET.SubElement(parent_node, "node", name = child_attr.name,
- extra_info = parser.get_item_description(child_attr.value),
- start_offset = str(child_attr.start_offset),
- end_offset = str(child_attr.end_offset),
- is_metavar = str(child_attr.is_metavar))
- recurse(child_attr.value, current_node, child_attr.is_array)
-
-
+ nonlocal reparse_needed
+
+ try:
+ if is_array:
+ values = parent_object
+ else:
+ values = parser.get_children(parent_object)
+
+ for child_attr in values:
+ current_node = ET.SubElement(parent_node, "node", name = child_attr.name,
+ extra_info = parser.get_item_description(child_attr.value),
+ start_offset = str(child_attr.start_offset),
+ end_offset = str(child_attr.end_offset),
+ is_metavar = str(child_attr.is_metavar))
+ recurse(child_attr.value, current_node, child_attr.is_array)
+ except model.PytaiUnparsedAccessException:
+ reparse_needed = True
+
+ max_retries = 5
with parser.parse(path) as parsed_file:
- recurse(parent_object = parsed_file, parent_node = root, is_array = False)
-
- return root
+ for _ in range(max_retries):
+ root = ET.Element("root")
+ recurse(parent_object = parsed_file, parent_node = root, is_array = False)
+ if reparse_needed:
+ reparse_needed = False
+ # Try again
+ else:
+ return root
+
+ raise RuntimeError(f"Could not parse {path}")
def save_kaitai_to_xml(kaitai_format: str, input_path: Union[str, Path], output_path: Union[str, Path]) -> None:
"""Save an XML representation of the given file to the given output path.
diff --git a/pytai/tests/resources/elf.xml b/pytai/tests/resources/elf.xml
index b113d2a..222bfc9 100644
--- a/pytai/tests/resources/elf.xml
+++ b/pytai/tests/resources/elf.xml
@@ -211,8 +211,8 @@
-
-
+
+
@@ -241,8 +241,8 @@
-
-
+
+
@@ -271,20 +271,20 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
@@ -313,20 +313,20 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
@@ -355,28 +355,28 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -385,137 +385,137 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -532,8 +532,8 @@
-
-
+
+
@@ -550,7 +550,7 @@
-
+
@@ -579,16 +579,16 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -597,137 +597,137 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -744,7 +744,7 @@
-
+
@@ -773,20 +773,20 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -815,28 +815,28 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -845,137 +845,137 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -992,8 +992,8 @@
-
-
+
+
@@ -1010,7 +1010,7 @@
-
+
@@ -1039,33 +1039,33 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -1082,7 +1082,7 @@
-
+
@@ -1111,71 +1111,71 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1184,137 +1184,137 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -1331,8 +1331,8 @@
-
-
+
+
@@ -1349,7 +1349,7 @@
-
+
@@ -1378,36 +1378,36 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1416,137 +1416,137 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -1563,8 +1563,8 @@
-
-
+
+
@@ -1581,7 +1581,7 @@
-
+
@@ -1610,8 +1610,8 @@
-
-
+
+
@@ -1640,8 +1640,8 @@
-
-
+
+
@@ -1670,8 +1670,8 @@
-
-
+
+
@@ -1700,8 +1700,8 @@
-
-
+
+
@@ -1730,8 +1730,8 @@
-
-
+
+
@@ -1760,8 +1760,8 @@
-
-
+
+
@@ -1790,8 +1790,8 @@
-
-
+
+
@@ -1820,8 +1820,8 @@
-
-
+
+
@@ -1850,8 +1850,8 @@
-
-
+
+
@@ -1880,8 +1880,8 @@
-
-
+
+
@@ -1910,134 +1910,134 @@
-
-
-
-
-
+
+
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
@@ -2069,57 +2069,57 @@
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -2127,31 +2127,31 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -2168,7 +2168,7 @@
-
+
@@ -2197,8 +2197,8 @@
-
-
+
+
@@ -2227,8 +2227,8 @@
-
-
+
+
@@ -2257,8 +2257,8 @@
-
-
+
+
@@ -2287,8 +2287,8 @@
-
-
+
+
@@ -2317,8 +2317,8 @@
-
-
+
+
@@ -2347,16 +2347,16 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -2365,14 +2365,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2381,14 +2381,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2397,14 +2397,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2413,14 +2413,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2429,14 +2429,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2445,14 +2445,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2461,14 +2461,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2477,14 +2477,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2493,14 +2493,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2509,14 +2509,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2525,14 +2525,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2541,14 +2541,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2557,14 +2557,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2573,14 +2573,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2589,14 +2589,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2605,14 +2605,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2621,14 +2621,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2637,14 +2637,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2653,14 +2653,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2669,14 +2669,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2685,14 +2685,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2701,14 +2701,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2717,14 +2717,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2733,14 +2733,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2749,14 +2749,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2765,14 +2765,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2781,201 +2781,201 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -2984,481 +2984,481 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -3475,7 +3475,7 @@
-
+
@@ -3504,41 +3504,41 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -3567,39 +3567,39 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+