From fd9838bcbaa6b2a6bf95ba9c9ee9b582f8e02e01 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 9 Aug 2022 10:17:31 +0200 Subject: [PATCH] improved the file connector algorithm --- fsfwgen/returnvalues/returnvalues_parser.py | 115 ++++++++++++++------ 1 file changed, 79 insertions(+), 36 deletions(-) diff --git a/fsfwgen/returnvalues/returnvalues_parser.py b/fsfwgen/returnvalues/returnvalues_parser.py index d0305e8..50fafd2 100644 --- a/fsfwgen/returnvalues/returnvalues_parser.py +++ b/fsfwgen/returnvalues/returnvalues_parser.py @@ -1,7 +1,8 @@ import re import sys +from dataclasses import dataclass from pathlib import Path -from typing import List, Tuple, Optional, Dict +from typing import List, Tuple, Optional, Dict, Union from fsfwgen.parserbase.parser import FileParser, VerbosityLevels from fsfwgen.utility.printer import PrettyPrinter @@ -20,14 +21,34 @@ DEFAULT_MOVING_WINDOWS_SIZE = 7 INVALID_IF_ID = -1 +@dataclass +class FileStartHelper: + start_name: str + start_name_or_value: str + count: int + cumulative_start_index: Optional[int] = None + + +@dataclass +class FileEndHelper: + end_name: str + cumulative_end_value: Optional[int] = None + + +@dataclass +class FileConnHelper: + file_name: str + sh: Optional[FileStartHelper] + eh: Optional[FileEndHelper] + + class InterfaceParser(FileParser): def __init__(self, file_list: list, print_table: bool = False): super().__init__(file_list) self.print_table = print_table self.file_table_list = [] self.file_name_table = [] - self.start_name_list = [] - self.end_name_list = [] + self.file_conn_helpers: Optional[List[FileConnHelper]] = None self._debug_mode = False def enable_debug_mode(self, enable: bool): @@ -60,23 +81,28 @@ class InterfaceParser(FileParser): start_matched = False end_matched = False start_name = "" - target_end_name = "" + first_entry_name_or_index = "" + file_conn_entry = FileConnHelper(file_name, None, None) for line in all_lines: if not start_matched: match = re.search(r"[\s]*([\w]*) = [\s]*([\w]*)", line) if match: # current_file_table.update({count: [match.group(1), match.group(2)]}) start_name = match.group(1) - target_end_name = match.group(2) + first_entry_name_or_index = match.group(2) start_matched = True else: match = re.search(r"[\s]*([\w]*),?(?:[\s]*//)?([^\n]*)?", line) if match: count += 1 + # It is expected that the last entry is explicitely marked like this. + # TODO: Could also simply remember last entry and then designate that as end + # entry as soon as "}" is found. Requires moving window mode though if re.search(r"\[EXPORT][\s]*:[\s]*\[END]", match.group(2)): last_entry_name = match.group(1) end_matched = True - self.end_name_list.append([last_entry_name, None]) + file_conn_entry.eh = FileEndHelper(last_entry_name, None) + break else: short_name = match.group(2) if short_name == "": @@ -94,50 +120,68 @@ class InterfaceParser(FileParser): "Make sure to use [EXPORT] : [END]" ) sys.exit(1) - self.start_name_list.append([start_name, target_end_name, None, count]) + file_conn_entry.sh = FileStartHelper( + start_name, first_entry_name_or_index, count, None + ) + if self.file_conn_helpers is None: + self.file_conn_helpers = [] + self.file_conn_helpers.append(file_conn_entry) self.file_name_table.append(file_name) self.file_table_list.append(current_file_table) def _post_parsing_operation(self): - self.start_name_list, self.end_name_list = self.__assign_start_end_indexes( - self.start_name_list, self.end_name_list - ) + self.__assign_start_end_indexes() + self._print_start_end_info() for idx, file_table in enumerate(self.file_table_list): - self.__build_mod_interface_table(self.start_name_list[idx][2], file_table) + self.__build_mod_interface_table( + self.file_conn_helpers[idx].sh.count, file_table + ) if self.print_table: PrettyPrinter.pprint(self.mib_table) - @staticmethod - def __assign_start_end_indexes( - start_name_list_list, end_name_list_list - ) -> Tuple[List, List]: - # TODO: Clean up this mess. Use a wrapper/helper class instead of wild list/indexes - # Also, the complexity of this algorithm warrants a unittest.. - start_list_list_completed = start_name_list_list - end_list_list_completed = end_name_list_list + def _print_start_end_info(self): + for conn_helper in self.file_conn_helpers: + print( + f"Detected {conn_helper.sh.count} entries in {conn_helper.file_name}, " + f"end index {conn_helper.eh.cumulative_end_value}" + ) + + def __assign_start_end_indexes(self): + conn_helpers_old = self.file_conn_helpers.copy() all_indexes_filled = False max_outer_iterations = 15 current_iteration = 0 while not all_indexes_filled: - for idx, start_name_list in enumerate(start_list_list_completed): - if start_name_list[1].isdigit(): - start_list_list_completed[idx][2] = int(start_name_list[1]) - end_list_list_completed[idx][1] = ( - start_list_list_completed[idx][2] - + start_list_list_completed[idx][3] + for idx, conn_helper in enumerate(conn_helpers_old): + sh = conn_helper.sh + # In the very first file, the first index might/will be a number + if sh.start_name_or_value.isdigit(): + sh.cumulative_start_index = int(sh.start_name_or_value) + conn_helpers_old[idx].eh.cumulative_end_value = ( + sh.cumulative_start_index + sh.count ) - target_end_name = start_name_list[1] - for end_name_list in end_list_list_completed: - end_name = end_name_list[0] - end_value = end_name_list[1] - if end_name == target_end_name and end_value is not None: - start_list_list_completed[idx][2] = end_value - end_list_list_completed[idx][1] = ( - end_value + start_list_list_completed[idx][3] + # Now, we try to connect the start and end of the files using the start and end + # names respectively + end_name_to_search = conn_helper.sh.start_name_or_value + for end_name_helper in conn_helpers_old: + eh = end_name_helper.eh + if ( + eh.end_name == end_name_to_search + and eh.cumulative_end_value is not None + ): + self.file_conn_helpers[ + idx + ].sh.cumulative_start_index = eh.cumulative_end_value + self.file_conn_helpers[idx].eh.cumulative_end_value = ( + eh.cumulative_end_value + + self.file_conn_helpers[idx].sh.count ) all_indexes_filled = True - for idx, start_name_list in enumerate(start_list_list_completed): - if start_name_list[2] is None or end_name_list_list[idx][1] is None: + for idx, conn_helper in enumerate(conn_helpers_old): + if ( + conn_helper.sh.cumulative_start_index is None + or conn_helper.eh.cumulative_end_value is None + ): all_indexes_filled = False current_iteration += 1 if current_iteration >= max_outer_iterations: @@ -146,7 +190,6 @@ class InterfaceParser(FileParser): "given number of maximum outer iterations!" ) sys.exit(1) - return start_list_list_completed, end_list_list_completed def __build_mod_interface_table(self, count_start: int, interface_dict: dict): dict_to_build = dict()