# Path: fmodpy/parsing/util.py
# def pop_group(list_str, open_with="(", close_with=")"):
#     group = []
#     # Get the first element of the string (open the group, if matched).
#     if ((len(list_str) > 0) and (list_str[0] == open_with)):
#         list_str.pop(0)
#         num_open = 1
#     else: num_open = 0
#     # Search until the started group is closed.
#     while (num_open > 0):
#         # TOOD: Might need to raise parsing error when this happens.
#         if (len(list_str) == 0): raise(NotImplementedError)
#         next_value = list_str.pop(0)
#         if   (next_value == open_with):  num_open += 1
#         elif (next_value == close_with): num_open -= 1
#         if (num_open != 0): group.append(next_value)
#     # Return the captured portion and the remaining.
#     return group, list_str


from . import pop_group
        import re # <- use regular expressions to capture SIZE(...) syntax.
                import warnings
            if (self.dimension is None) and (self.type != "TYPE"):
                value += ".value"
            # Return None for missing optional returns.
            if self.optional: names.append(f"({value} if {py_name}_present else None)")
            else:             names.append(f"{value}")
        # Return the processed name.
        return names

    # ----------------------------------------------------------------
    #                    Module Attribute Access

    # Define a 'getter' function in Python for a public module attribute.
    def py_getter(self):
        py_name = self.name.lower()
        call_args = []
        lines = [f'def get_{py_name}(self):']
        # If this is not in a MODULE, then that was unexpected.
        if ((self.parent == None) or (self.parent.type != "MODULE")):
            raise(NotImplementedError)
        # If this module attribute is allocatable, we might need to return None.
        if (self.allocatable):
            call_args.append(f'ctypes.byref({py_name}_allocated)')
            lines.append(f'    {py_name}_allocated = ctypes.c_bool(False)')
        # Define the dimension size variables if appropriate.
        if (self.dimension is not None):
            for i in range(len(self.dimension)):
                lines.append(f'    {py_name}_dim_{i+1} = ctypes.c_int()')
                call_args.append(f'ctypes.byref({py_name}_dim_{i+1})')
                # Define the actual attribute holder itself.
        if (self.allocatable or (self.dimension is not None)):

# Path: fmodpy/parsing/util.py
# def pop_group(list_str, open_with="(", close_with=")"):
#     group = []
#     # Get the first element of the string (open the group, if matched).
#     if ((len(list_str) > 0) and (list_str[0] == open_with)):
#         list_str.pop(0)
#         num_open = 1
#     else: num_open = 0
#     # Search until the started group is closed.
#     while (num_open > 0):
#         # TOOD: Might need to raise parsing error when this happens.
#         if (len(list_str) == 0): raise(NotImplementedError)
#         next_value = list_str.pop(0)
#         if   (next_value == open_with):  num_open += 1
#         elif (next_value == close_with): num_open -= 1
#         if (num_open != 0): group.append(next_value)
#     # Return the captured portion and the remaining.
#     return group, list_str


# Path: fmodpy/parsing/argument.py
from . import pop_group
        import re # <- use regular expressions to capture SIZE(...) syntax.
                import warnings

            if (self.dimension is None) and (self.type != "TYPE"):
                value += ".value"
            # Return None for missing optional returns.
            if self.optional: names.append(f"({value} if {py_name}_present else None)")
            else:             names.append(f"{value}")
        # Return the processed name.
        return names

    # ----------------------------------------------------------------
    #                    Module Attribute Access

    # Define a 'getter' function in Python for a public module attribute.
    def py_getter(self):
        py_name = self.name.lower()
        call_args = []
        lines = [f'def get_{py_name}(self):']
        # If this is not in a MODULE, then that was unexpected.
        if ((self.parent == None) or (self.parent.type != "MODULE")):
            raise(NotImplementedError)
        # If this module attribute is allocatable, we might need to return None.
        if (self.allocatable):
            call_args.append(f'ctypes.byref({py_name}_allocated)')
            lines.append(f'    {py_name}_allocated = ctypes.c_bool(False)')
        # Define the dimension size variables if appropriate.
        if (self.dimension is not None):
            for i in range(len(self.dimension)):
                lines.append(f'    {py_name}_dim_{i+1} = ctypes.c_int()')
                call_args.append(f'ctypes.byref({py_name}_dim_{i+1})')
                # Define the actual attribute holder itself.
        if (self.allocatable or (self.dimension is not None)):

            lines += [f'    {py_name} = ctypes.c_void_p()']