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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - +