def _resolve_rule_refs(self, grammar_parser, model_parser):
        """Resolves parser ParsingExpression crossrefs."""

        resolved_set = set()

        def resolve(node):
            """
            Recursively resolve peg rule references and textx rule types.

            Args:
                node(ParsingExpression or RuleCrossRef)
            """

            def _inner_resolve(rule):
                if grammar_parser.debug:
                    grammar_parser.dprint("Resolving rule: {}".format(rule))

                # Save initial rule name to detect special abstract rule case.
                initial_rule_name = rule.rule_name

                if type(rule) is RuleCrossRef:
                    rule_name = rule.rule_name
                    if rule_name in model_parser.metamodel:
                        rule = model_parser.metamodel[rule_name]._tx_peg_rule
                        if type(rule) is RuleCrossRef:
                            rule = _inner_resolve(rule)
                            model_parser.metamodel[rule_name]\
                                ._tx_peg_rule = rule
                    else:
                        line, col = grammar_parser.pos_to_linecol(rule.position)
                        raise TextXSemanticError(
                            'Unexisting rule "{}" at position {}.'
                            .format(rule.rule_name,
                                    (line, col)), line, col)

                assert isinstance(rule, ParsingExpression),\
                    "{}:{}".format(type(rule), text(rule))

                # If there is meta-class attributes collected than this
                # is common rule
                if hasattr(rule, '_tx_class') and \
                        len(rule._tx_class._tx_attrs) > 0:
                    rule._tx_class._tx_type = RULE_COMMON

                # Recurse into subrules, resolve and determine rule types.
                abstract = False
                for idx, child in enumerate(rule.nodes):
                    if child not in resolved_set:
                        resolved_set.add(rule)
                        child = _inner_resolve(child)
                        rule.nodes[idx] = child

                    # Detect abstract rules.
                    if rule.rule_name != initial_rule_name:
                        # Special case when there is only a single rule ref in
                        # the rule.
                        abstract = True
                    elif rule.root and \
                            not rule.rule_name.startswith('__asgn') and \
                            hasattr(child, '_tx_class') and \
                            isinstance(rule, OrderedChoice):
                        # If this is root rule, OrderedChoice, and its not
                        # assignment and there exists child that has its meta-class
                        # which is abstract or common than this must be abstract.
                        abstract |= child._tx_class._tx_type != RULE_MATCH

                if abstract:
                    cls = model_parser.metamodel[initial_rule_name]
                    cls._tx_type = RULE_ABSTRACT
                    # Add inherited classes to this rule's meta-class
                    for idx, child in enumerate(rule.nodes):
                        if child.root and hasattr(child, '_tx_class'):
                            if child._tx_class not in cls._tx_inh_by:
                                cls._tx_inh_by.append(child._tx_class)

                return rule

            resolved_set.add(node)
            _inner_resolve(node)

        if grammar_parser.debug:
            grammar_parser.dprint("RESOLVING RULE CROSS-REFS")

        for cls in model_parser.metamodel:
            resolve(cls._tx_peg_rule)
dataset/ETHPy150Open igordejanovic/textX/textx/textx.py/TextXModelSA._resolve_rule_refs/original