def parse(self, dictionary=None, end_token=None):
        """
        Parse through the tokens. Finding names and values.
        This is called at the start of parsing the config but is
        also called to parse module definitions.
        """
        self.level += 1
        name = []
        if dictionary is None:
            dictionary = self.config
        while True:
            token = self.next()
            if token is None:
                # we have got to the end of the config
                break
            t_type = token["type"]
            t_value = token["value"]
            if t_type == "newline":
                continue
            elif t_value == end_token:
                self.level -= 1
                return
            elif t_type == "literal":
                value = self.remove_quotes(t_value)
                if not name and not re.match("[a-zA-Z_]", value):
                    self.error("Invalid name")
                name.append(value)
            elif t_type == "function":
                self.error("Name expected")
            elif t_type == "operator":
                name = " ".join(name)
                if not name:
                    self.error("Name expected")
                elif t_value == "+=" and name not in dictionary:
                    # deal with encoded names
                    if name.split(":")[0] not in dictionary:
                        # order is treated specially
                        if not (self.level == 1 and name == "order"):
                            self.error(f"{name} does not exist")
                if t_value in ["{"]:
                    if self.current_module:
                        self.check_child_friendly(self.current_module[-1])
                    self.check_module_name(name)
                    self.current_module.append(name)
                value = self.assignment(token)
                # order is treated specially to create a list
                if self.level == 1 and name == "order":
                    if not value:
                        self.error("Invalid module")
                    self.check_module_name(value, offset=1)
                    dictionary.setdefault(name, []).append(value)
                # assignment of  module definition
                elif t_value == "{":
                    # If this is an py3status module and in a container and has
                    # no instance name then give it an anon one.  This allows
                    # us to have multiple non-instance named modules defined
                    # without them clashing.
                    if self.level > 1 and " " not in name and name not in I3S_MODULE_NAMES:
                        name = f"{name} _anon_module_{self.anon_count}"
                        self.anon_count += 1
                    dictionary[name] = value
                # assignment of value
                elif t_value == "=":
                    try:
                        name, value = self.process_value(name, value, self.current_module[-1])
                    except IndexError:
                        self.error("Missing {", previous=True)
                    dictionary[name] = value
                # appending to existing values
                elif t_value == "+=":
                    dictionary[name] += value
                else:
                    self.error("Unexpected character")
                name = []

        Parse through the tokens. Finding names and values.
        This is called at the start of parsing the config but is
        also called to parse module definitions.
        
py3status/parse_config.py