<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def parse(self, valstr):
        # type: (bytes) -> bool
        '''
        A method to parse an El Torito Boot Catalog out of a string.

        Parameters:
         valstr - The string to parse the El Torito Boot Catalog out of.
        Returns:
         Nothing.
        '''
        if self._initialized:
            raise pycdlibexception.PyCdlibInternalError('El Torito Boot Catalog already initialized')

        if self.state == self.EXPECTING_VALIDATION_ENTRY:
            # The first entry in an El Torito boot catalog is the Validation
            # Entry.  A Validation entry consists of 32 bytes (described in
            # detail in the parse_eltorito_validation_entry() method).
            self.validation_entry.parse(valstr)
            self.state = self.EXPECTING_INITIAL_ENTRY
        elif self.state == self.EXPECTING_INITIAL_ENTRY:
            # The next entry is the Initial/Default entry.  An Initial/Default
            # entry consists of 32 bytes (described in detail in the
            # parse_eltorito_initial_entry() method).
            self.initial_entry.parse(valstr)
            self.state = self.EXPECTING_SECTION_HEADER_OR_DONE
        else:
            val = bytes(bytearray([valstr[0]]))
            if val == b'\x00':
                # An empty entry tells us we are done parsing El Torito.  Do
                # some sanity checks.
                last_section_index = len(self.sections) - 1
                for index, sec in enumerate(self.sections):
                    if sec.num_section_entries != len(sec.section_entries):
                        raise pycdlibexception.PyCdlibInvalidISO('El Torito section header specified %d entries, only saw %d' % (sec.num_section_entries, len(sec.section_entries)))
                    if index != last_section_index:
                        if sec.header_indicator != 0x90:
                            raise pycdlibexception.PyCdlibInvalidISO('Intermediate El Torito section header not properly specified')
                    # In theory, we should also make sure that the very last
                    # section has a header_indicator of 0x91.  However, we
                    # have seen ISOs in the wild (FreeBSD 11.0 amd64) in which
                    # this is not the case, so we skip that check.
                self._initialized = True
            elif val in (b'\x90', b'\x91'):
                # A Section Header Entry
                section_header = EltoritoSectionHeader()
                section_header.parse(valstr)
                self.sections.append(section_header)
            elif val in (b'\x88', b'\x00'):
                # A Section Entry. According to El Torito 2.4, a Section Entry
                # must follow a Section Header, but we have seen ISOs in the
                # wild that do not follow this (Mageia 4 ISOs, for instance).
                # To deal with this, we get a little complicated here.  If there
                # is a previous section header, and the length of the entries
                # attached to it is less than the number of entries it should
                # have, then we attach this entry to that header.  If there is
                # no previous section header, or if the previous section header
                # is already 'full', then we make this a standalone entry.
                secentry = EltoritoEntry()
                secentry.parse(valstr)
                if self.sections and len(self.sections[-1].section_entries) < self.sections[-1].num_section_entries:
                    self.sections[-1].add_parsed_entry(secentry)
                else:
                    self.standalone_entries.append(secentry)
            elif val == b'\x44':
                # A Section Entry Extension
                self.sections[-1].section_entries[-1].selection_criteria += valstr[2:]
            else:
                raise pycdlibexception.PyCdlibInvalidISO('Invalid El Torito Boot Catalog entry')

        return self._initialized