def test_textx_isinstace():
    grammar = \
        '''
    Model: a=A;
    A: B;
    B: C;
    C: x=ID;
    '''
    my_meta_model = metamodel_from_str(grammar)
    A = my_meta_model['A']
    B = my_meta_model['B']
    C = my_meta_model['C']
    my_model = my_meta_model.model_from_str("c")
    c = get_children_of_type("C", my_model)
    assert len(c) == 1
    c = c[0]
    assert textx_isinstance(c, C)
    assert textx_isinstance(c, B)
    assert textx_isinstance(c, A)
Example #2
0
def test_textx_issue155():
    import textx

    METAMODEL = textx.metamodel_from_str("""
    Model: expression=Expr ;

    ParenExpr: '(' Expr ')';
    Expr: ParenExpr | BaseExpr;
    BaseExpr: left=Condition operations*=Operation;
    Operation:  op=BoolOperator remaining=Condition;

    Condition: ParenExpr | RawCondition;
    RawCondition: id=Identifier op=MathOperator val=INT;

    Identifier: id=/[a-zA-Z0-9_-]+/;
    MathOperator:  op=/=|>|</;
    BoolOperator:  op=/AND|OR/;
    """)

    from textx.scoping.tools import textx_isinstance

    m1 = METAMODEL.model_from_str('(b=3 OR c=4)')
    assert textx_isinstance(m1.expression, METAMODEL['BaseExpr'])
    assert textx_isinstance(m1.expression.left, METAMODEL['RawCondition'])
    assert len(m1.expression.operations) == 1
    assert m1.expression.operations[0].op.op == 'OR'
    assert textx_isinstance(m1.expression.operations[0].remaining,
                            METAMODEL['RawCondition'])

    m2 = METAMODEL.model_from_str('a=2 AND (b=3 OR c=4)')
    assert textx_isinstance(m2.expression, METAMODEL['BaseExpr'])
    assert textx_isinstance(m2.expression.left, METAMODEL['RawCondition'])
    assert len(m2.expression.operations) == 1
    assert m2.expression.operations[0].op.op == 'AND'
    assert textx_isinstance(m2.expression.operations[0].remaining,
                            METAMODEL['BaseExpr'])
    assert textx_isinstance(m2.expression.operations[0].remaining.left,
                            METAMODEL['RawCondition'])
    assert len(m2.expression.operations[0].remaining.operations) == 1
    assert m2.expression.operations[0].remaining.operations[0].op.op == 'OR'
    assert textx_isinstance(m2.expression.operations[0].remaining.
                            operations[0].remaining,
                            METAMODEL['RawCondition'])
Example #3
0
def test_textx_issue155():
    import textx

    METAMODEL = textx.metamodel_from_str("""
    Model: expression=Expr ;

    ParenExpr: '(' Expr ')';
    Expr: ParenExpr | BaseExpr;
    BaseExpr: left=Condition operations*=Operation;
    Operation:  op=BoolOperator remaining=Condition;

    Condition: ParenExpr | RawCondition;
    RawCondition: id=Identifier op=MathOperator val=INT;

    Identifier: id=/[a-zA-Z0-9_-]+/;
    MathOperator:  op=/=|>|</;
    BoolOperator:  op=/AND|OR/;
    """)

    from textx.scoping.tools import textx_isinstance

    m1 = METAMODEL.model_from_str('(b=3 OR c=4)')
    assert textx_isinstance(m1.expression, METAMODEL['BaseExpr'])
    assert textx_isinstance(m1.expression.left, METAMODEL['RawCondition'])
    assert len(m1.expression.operations) == 1
    assert m1.expression.operations[0].op.op == 'OR'
    assert textx_isinstance(m1.expression.operations[0].remaining,
                            METAMODEL['RawCondition'])

    m2 = METAMODEL.model_from_str('a=2 AND (b=3 OR c=4)')
    assert textx_isinstance(m2.expression, METAMODEL['BaseExpr'])
    assert textx_isinstance(m2.expression.left, METAMODEL['RawCondition'])
    assert len(m2.expression.operations) == 1
    assert m2.expression.operations[0].op.op == 'AND'
    assert textx_isinstance(m2.expression.operations[0].remaining,
                            METAMODEL['BaseExpr'])
    assert textx_isinstance(m2.expression.operations[0].remaining.left,
                            METAMODEL['RawCondition'])
    assert len(m2.expression.operations[0].remaining.operations) == 1
    assert m2.expression.operations[0].remaining.operations[0].op.op == 'OR'
    assert textx_isinstance(
        m2.expression.operations[0].remaining.operations[0].remaining,
        METAMODEL['RawCondition'])
Example #4
0
        def _find_obj_fqn(p, fqn_name, cls):
            """
            Helper function:
            find a named object based on a qualified name ("."-separated
            names) starting from object p.

            Args:
                p: the container where to start the search
                fqn_name: the "."-separated name

            Returns:
                the object or None
            """
            def find_obj(parent, name):
                for attr in [
                        a for a in parent.__dict__
                        if not a.startswith('__') and not a.startswith('_tx_')
                        and not callable(getattr(parent, a))
                ]:
                    obj = getattr(parent, attr)
                    if isinstance(obj, (list, tuple)):
                        for innerobj in obj:
                            if hasattr(innerobj, "name") \
                                    and innerobj.name == name:
                                return innerobj
                    else:
                        if hasattr(obj, "name") and obj.name == name:
                            return obj
                return None

            for n in fqn_name.split('.'):
                obj = find_obj(p, n)
                if obj:
                    p = obj
                else:
                    return None

            from textx.scoping.tools import textx_isinstance
            if textx_isinstance(obj, cls):
                return p
            else:
                return None
Example #5
0
    def __call__(self, obj, attr, obj_ref):
        """
        the default scope provider

        Args:
            obj: unused (used for multi_metamodel_support)
            attr: unused
            obj_ref: the cross reference to be resolved

        Returns:
            the resolved reference or None
        """
        from textx.const import RULE_COMMON, RULE_ABSTRACT
        from textx.model import ObjCrossRef
        from textx.scoping.tools import get_parser

        if obj_ref is None:
            return None  # an error! (see model.py: resolve_refs (TODO check)

        assert type(obj_ref) is ObjCrossRef, type(obj_ref)

        if get_parser(obj).debug:
            get_parser(obj).dprint("Resolving obj crossref: {}:{}".format(
                obj_ref.cls, obj_ref.obj_name))

        def _inner_resolve_link_rule_ref(cls, obj_name):
            """
            Depth-first resolving of link rule reference.
            """
            if cls._tx_type is RULE_ABSTRACT:
                for inherited in cls._tx_inh_by:
                    result = _inner_resolve_link_rule_ref(inherited, obj_name)
                    if result:
                        return result
            elif cls._tx_type == RULE_COMMON:
                # TODO make this code exchangable
                # allow to know the current attribute (model location for
                # namespace) and to navigate through the whole model...
                # OR (with another scope provider) to make custom lookups in
                # the model
                #
                # Scopeprovider
                # - needs: .current reference (in the model)
                #          .the model (?)
                # - provides: the resolved object or None
                if id(cls) in get_parser(obj)._instances:
                    objs = get_parser(obj)._instances[id(cls)]
                    if obj_name in objs:
                        return objs[obj_name]

        if self.multi_metamodel_support:
            from textx import get_model, get_children
            from textx.scoping.tools import textx_isinstance
            result_lst = get_children(
                lambda x: hasattr(x, "name") and x.name == obj_ref.obj_name and
                textx_isinstance(x, obj_ref.cls), get_model(obj))
            if len(result_lst) == 1:
                result = result_lst[0]
            elif len(result_lst) > 1:
                line, col = get_parser(obj).pos_to_linecol(obj_ref.position)
                raise TextXSemanticError("name {} is not unique.".format(
                    obj_ref.obj_name),
                                         line=line,
                                         col=col,
                                         filename=get_model(obj)._tx_filename)
            else:
                result = None
        else:
            result = _inner_resolve_link_rule_ref(obj_ref.cls,
                                                  obj_ref.obj_name)
        if result:
            return result

        return None  # error handled outside