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)
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'])
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'])
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
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