Ejemplo n.º 1
0
    def resolve_refs(model):
        """
        Resolves model references.
        """
        metamodel = parser.metamodel

        current_crossrefs = parser._crossrefs
        new_crossrefs = []
        delayed_crossrefs = []
        resolved_crossref_count = 0

        # -------------------------
        # start of resolve-loop
        # -------------------------
        default_scope = DefaultScopeProvider()
        for obj, attr, crossref in current_crossrefs:
            if (get_model(obj) == model):
                attr_value = getattr(obj, attr.name)
                attr_refs = [
                    obj.__class__.__name__ + "." + attr.name, "*." + attr.name,
                    obj.__class__.__name__ + ".*", "*.*"
                ]
                for attr_ref in attr_refs:
                    if attr_ref in metamodel.scope_providers:
                        if parser.debug:
                            parser.dprint(" FOUND {}".format(attr_ref))
                        resolved = metamodel.scope_providers[attr_ref](
                            parser, obj, attr, crossref)
                        break
                else:
                    resolved = default_scope(parser, obj, attr, crossref)

                # Collect cross-references for textx-tools
                if resolved and not type(resolved) is Postponed:
                    if metamodel.textx_tools_support:
                        pos_crossref_list.append(
                            RefRulePosition(
                                name=crossref.obj_name,
                                ref_pos_start=crossref.position,
                                ref_pos_end=crossref.position +
                                len(resolved.name),
                                def_pos_start=resolved._tx_position,
                                def_pos_end=resolved._tx_position_end))

                if not resolved:
                    # As a fall-back search builtins if given
                    if metamodel.builtins:
                        if crossref.obj_name in metamodel.builtins:
                            # TODO: Classes must match
                            resolved = metamodel.builtins[crossref.obj_name]

                if not resolved:
                    line, col = parser.pos_to_linecol(crossref.position)
                    raise TextXSemanticError(
                        message='Unknown object "{}" of class "{}" at {}'.
                        format(crossref.obj_name, crossref.cls.__name__,
                               (line, col)),
                        line=line,
                        col=col,
                        err_type=UNKNOWN_OBJ_ERROR,
                        expected_obj_cls=crossref.cls)

                if type(resolved) is Postponed:
                    delayed_crossrefs.append((obj, attr, crossref))
                    new_crossrefs.append((obj, attr, crossref))
                else:
                    resolved_crossref_count += 1
                    if attr.mult in [MULT_ONEORMORE, MULT_ZEROORMORE]:
                        attr_value.append(resolved)
                    else:
                        setattr(obj, attr.name, resolved)
            else:  # crossref not in model
                new_crossrefs.append((obj, attr, crossref))
        # -------------------------
        # end of resolve-loop
        # -------------------------
        # store cross-refs from other models in the parser list (for later
        # processing) this happens when other models are loaded while parsing
        # one model.
        parser._crossrefs = new_crossrefs
        return (resolved_crossref_count, delayed_crossrefs)
Ejemplo n.º 2
0
    def resolve_one_step(self):
        """
        Resolves model references.
        """
        metamodel = self.parser.metamodel

        current_crossrefs = self.parser._crossrefs
        # print("DEBUG: Current crossrefs #: {}".
        #      format(len(current_crossrefs)))
        new_crossrefs = []
        self.delayed_crossrefs = []
        resolved_crossref_count = 0

        # -------------------------
        # start of resolve-loop
        # -------------------------
        default_scope = DefaultScopeProvider()
        for obj, attr, crossref in current_crossrefs:
            if (get_model(obj) == self.model):
                attr_value = getattr(obj, attr.name)
                attr_refs = [
                    obj.__class__.__name__ + "." + attr.name, "*." + attr.name,
                    obj.__class__.__name__ + ".*", "*.*"
                ]
                if crossref.scope_provider is not None:
                    resolved = crossref.scope_provider(obj, attr, crossref)
                else:
                    for attr_ref in attr_refs:
                        if attr_ref in metamodel.scope_providers:
                            if self.parser.debug:
                                self.parser.dprint(
                                    " FOUND {}".format(attr_ref))
                            resolved = metamodel.scope_providers[attr_ref](
                                obj, attr, crossref)
                            break
                    else:
                        resolved = default_scope(obj, attr, crossref)

                # Collect cross-references for textx-tools
                if resolved is not None and not type(resolved) is Postponed:
                    if metamodel.textx_tools_support:
                        self.pos_crossref_list.append(
                            RefRulePosition(
                                name=crossref.obj_name,
                                ref_pos_start=crossref.position,
                                ref_pos_end=crossref.position +
                                len(resolved.name),
                                def_pos_start=resolved._tx_position,
                                def_pos_end=resolved._tx_position_end))

                if resolved is None:
                    # As a fall-back search builtins if given
                    if metamodel.builtins:
                        if crossref.obj_name in metamodel.builtins:
                            from textx import textx_isinstance
                            if textx_isinstance(
                                    metamodel.builtins[crossref.obj_name],
                                    crossref.cls):
                                resolved = metamodel.builtins[
                                    crossref.obj_name]

                if resolved is None:
                    line, col = self.parser.pos_to_linecol(crossref.position)
                    raise TextXSemanticError(
                        message='Unknown object "{}" of class "{}"'.format(
                            crossref.obj_name, crossref.cls.__name__),
                        line=line,
                        col=col,
                        err_type=UNKNOWN_OBJ_ERROR,
                        expected_obj_cls=crossref.cls,
                        filename=self.model._tx_filename)

                if type(resolved) is Postponed:
                    self.delayed_crossrefs.append((obj, attr, crossref))
                    new_crossrefs.append((obj, attr, crossref))
                else:
                    resolved_crossref_count += 1
                    if attr.mult in [MULT_ONEORMORE, MULT_ZEROORMORE]:
                        attr_value.append(resolved)
                    else:
                        setattr(obj, attr.name, resolved)
            else:  # crossref not in model
                new_crossrefs.append((obj, attr, crossref))
        # -------------------------
        # end of resolve-loop
        # -------------------------
        # store cross-refs from other models in the parser list (for later
        # processing)
        self.parser._crossrefs = new_crossrefs
        # print("DEBUG: Next crossrefs #: {}".format(len(new_crossrefs)))
        return (resolved_crossref_count, self.delayed_crossrefs)