Add rules into the set. Each rule is validated and split if needed.
        The method add the rules into dictionary, so the rule can be deleted with terminals or nonterminals.
        :param rules: Rules to insert.
        :return: Inserted rules.
        :raise NotRuleException: If the parameter doesn't inherit from Rule.
        :raise RuleException: If the syntax of the rule is invalid.

def _add(self, *rules):
        # type: (Iterable[Type[Rule]]) -> Generator[Type[Rule]]
        """
        Add rules into the set. Each rule is validated and split if needed.
        The method add the rules into dictionary, so the rule can be deleted with terminals or nonterminals.
        :param rules: Rules to insert.
        :return: Inserted rules.
        :raise NotRuleException: If the parameter doesn't inherit from Rule.
        :raise RuleException: If the syntax of the rule is invalid.
        """
        for rule in rules:
            if rule in self:
                continue
            self._validate_rule(rule)
        for rule in rules:
            for r in self._split_rules(rule):
                for side in r.rule:
                    for s in side:
                        self._assign_map[s].add(r)
                super().add(r)
                yield r