several bugfixes and improvements

This commit is contained in:
Robin Müller 2021-08-02 12:49:10 +02:00
parent 8e805d2408
commit 16280cc1df
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
3 changed files with 70 additions and 29 deletions

View File

@ -1,37 +1,37 @@
"""
@file file_list_parser.py
@brief Generic File Parser class
@details
"""Generic File Parser class
Used by parse header files. Implemented as class in case header parser becomes more complex
@author R. Mueller
@date 22.11.2019
"""
import os
import re
from typing import Union
from fsfwgen.core import get_console_logger
LOGGER = get_console_logger()
# pylint: disable=too-few-public-methods
class FileListParser:
"""
Generic header parser which takes a directory name or directory name list
"""Generic header parser which takes a directory name or directory name list
and parses all included header files recursively.
TODO: Filter functionality for each directory to filter out files or folders
"""
def __init__(self, directory_list_or_name: Union[str, list]):
self.directory_list = []
if isinstance(directory_list_or_name, str):
self.directory_list = [directory_list_or_name]
self.directory_list.append(directory_list_or_name)
elif isinstance(directory_list_or_name, list):
self.directory_list = directory_list_or_name
self.directory_list.extend(directory_list_or_name)
else:
print("Header Parser: Passed directory list is not a header name or list of "
"header names")
LOGGER.warning(
"Header Parser: Passed directory list is not a header name or list of header names"
)
self.header_files = []
def parse_header_files(self, search_recursively: bool = False,
printout_string: str = "Parsing header files: ",
print_current_dir: bool = False):
"""
This function is called to get a list of header files
"""This function is called to get a list of header files
:param search_recursively:
:param printout_string:
:param print_current_dir:

View File

@ -17,6 +17,12 @@ from abc import abstractmethod
from typing import Dict, List
class VerbosityLevels(enum.Enum):
REDUCED = 0,
REGULAR = 1,
DEBUG = 2
class FileParserModes(enum.Enum):
REGULAR = enum.auto(),
MOVING_WINDOW = enum.auto()
@ -72,6 +78,9 @@ class FileParser:
def set_verbosity(self, verbose_level: int):
self._verbose_level = verbose_level
def get_verbosity(self):
return self._verbose_level
def enable_moving_window_debugging(self, file_name: str):
self.__debug_moving_window = True
self.__debug_moving_window_filename = file_name
@ -201,6 +210,8 @@ class FileParser:
def _build_multi_line_string_generic(
self, first_line: str, moving_window: List[str]
) -> str:
"""This function transforms a multi line match into a one line match by searching for the
semicolon at the string end"""
all_lines = first_line.rstrip()
end_found = False
current_idx = self._moving_window_center_idx

View File

@ -2,19 +2,21 @@ import re
import sys
from typing import List, Tuple
from fsfwgen.parserbase.parser import FileParser
from fsfwgen.parserbase.parser import FileParser, VerbosityLevels
from fsfwgen.utility.printer import PrettyPrinter
from fsfwgen.core import get_console_logger
LOGGER = get_console_logger()
# Intermediate solution
MAX_STRING_LEN = 80
PRINT_TRUNCATED_ENTRIES = False
DEBUG_INTERFACE_ID_COMPARISON = False
DEBUG_FOR_FILE_NAME = False
DEBUG_FILE_NAME = "RingBufferAnalyzer"
CLASS_ID_NAMESPACE = "CLASS_ID"
DEFAULT_MOVING_WINDOWS_SIZE = 7
INVALID_IF_ID = -1
class InterfaceParser(FileParser):
@ -26,6 +28,10 @@ class InterfaceParser(FileParser):
self.file_name_table = []
self.start_name_list = []
self.end_name_list = []
self._debug_mode = False
def enable_debug_mode(self, enable: bool):
self._debug_mode = enable
def _handle_file_parsing_moving_window(
self, file_name: str, current_line: int, moving_window_size: int, moving_window: list,
@ -182,7 +188,7 @@ class ReturnValueParser(FileParser):
):
"""Parse for returnvalues using a moving window"""
interface_id_match = re.search(
rf"{CLASS_ID_NAMESPACE}::([a-zA-Z_0-9]*)", moving_window[self._moving_window_center_idx]
rf'{CLASS_ID_NAMESPACE}::([a-zA-Z_0-9]*)', moving_window[self._moving_window_center_idx]
)
if interface_id_match:
@ -202,22 +208,36 @@ class ReturnValueParser(FileParser):
moving_window=moving_window,
first_line=moving_window[self._moving_window_center_idx]
)
number_match = INVALID_IF_ID
# Try to match for a string using the new API first. Example:
# static const ReturnValue_t PACKET_TOO_LONG =
# HasReturnvaluesIF::makeReturnCode(CLASS_ID, 0);
returnvalue_match = re.search(
r"^[\s]*static const(?:expr)? ReturnValue_t[\s]*([\w] *)[\s]*"
r"^[\s]*static const(?:expr)? ReturnValue_t[\s]*([\w]*)[\s]*"
r"=[\s]*.*::[\w]*\(([\w]*),[\s]*([\d]*)\)",
full_returnvalue_string
)
if not returnvalue_match:
# Try to match for old API using MAE_RETURN_CODE macro
returnvalue_match = re.search(
r'^[\s]*static const(?:expr)? ReturnValue_t[\s]*([a-zA-Z_0-9]*)[\s]*=[\s]*'
r'MAKE_RETURN_CODE[\s]*\([\s]*([\w]*)[\s]*\)',
full_returnvalue_string
)
if returnvalue_match:
number_match = returnvalue_match.group(2)
else:
number_match = returnvalue_match.group(3)
if returnvalue_match:
description = self.__search_for_descrip_string(moving_window=moving_window)
if number_match == INVALID_IF_ID:
LOGGER.warning(f'Invalid number match detected for file {file_name}')
LOGGER.warning(f'Match groups:')
for group in returnvalue_match.groups():
LOGGER.info(group)
self.__handle_returnvalue_match(
name_match=returnvalue_match.group(1), file_name=file_name,
number_match=returnvalue_match.group(2), description=description
number_match=number_match, description=description
)
def __build_multi_line_returnvalue_string(
@ -256,17 +276,27 @@ class ReturnValueParser(FileParser):
self.last_lines[1] = self.last_lines[0]
self.last_lines[0] = newline
def __handle_interfaceid_match(self, interface_id_match, file_name: str):
if DEBUG_INTERFACE_ID_COMPARISON:
print(f"Interface ID {interface_id_match.group(1)} found in {file_name}")
self.current_interface_id_entries["ID"] = \
self.interfaces[interface_id_match.group(1)][0]
def __handle_interfaceid_match(self, interface_id_match, file_name: str) -> bool:
"""Handle a match of an interface ID definition in the code.
Returns whether the interface ID was found successfully in the IF ID header files
"""
if self.get_verbosity() == VerbosityLevels.DEBUG:
LOGGER.info(f'Interface ID {interface_id_match.group(1)} found in {file_name}')
if_id_entry = self.interfaces.get(interface_id_match.group(1))
if if_id_entry is not None:
self.current_interface_id_entries["ID"] = if_id_entry[0]
else:
LOGGER.warning(
f'Interface ID {interface_id_match.group(1)} not found in IF ID dictionary'
)
return False
self.current_interface_id_entries["Name"] = \
self.interfaces[interface_id_match.group(1)][1]
self.current_interface_id_entries["FullName"] = interface_id_match.group(1)
if DEBUG_INTERFACE_ID_COMPARISON:
if self.get_verbosity() == VerbosityLevels.DEBUG:
current_id = self.current_interface_id_entries["ID"]
print(f"Current ID: {current_id}")
LOGGER.info(f'Current ID: {current_id}')
return True
def __handle_returnvalue_match(
self, name_match: str, number_match: str, file_name: str, description: str
@ -312,7 +342,7 @@ class ReturnValueParser(FileParser):
my_str = first_part + '_' + self.convert(second_part)
if len(my_str) > max_string_len:
if print_truncated_entries:
print("Warning: Entry " + my_str + " too long. Will truncate.")
LOGGER.warning(f'Entry {my_str} too long. Will truncate.')
my_str = my_str[0:max_string_len]
else:
# print("Entry: " + myStr + " is all right.")
@ -342,6 +372,6 @@ def return_number_from_string(a_string):
return int(a_string, 16)
if a_string.isdigit():
return int(a_string)
print('Error: Illegal number representation: ' + a_string)
LOGGER.warning(f'Illegal number representation: {a_string}')
return 0