Beispiel #1
0
        def ref_scope(refItem, myattr, attr_ref):
            from textx.scoping.tools import get_named_obj_in_list
            from textx.scoping import Postponed
            from textx import textx_isinstance

            reference = refItem.parent

            if reference is None:
                return Postponed()

            index = list(map(lambda x: id(x),
                             reference.refs)).index(id(refItem))

            assert index >= 0

            base = reference.instance if index == 0 \
                else reference.refs[index - 1].valref
            if base is None or base.type is None:
                return Postponed()
            x = get_named_obj_in_list(base.type.vals, attr_ref.obj_name)
            if index == len(reference.refs) - 1:
                if not textx_isinstance(x, myattr.cls):
                    print(x)
                    return None

            return x
Beispiel #2
0
 def lookup(obj):
     if needs_to_be_resolved(obj, self.name):
         return Postponed(), lookup_list, matched_path
     if hasattr(obj, self.name):
         target = getattr(obj, self.name)
         if not self.consume_name and self.fixed_name is None:
             return target, lookup_list, matched_path  # return list
         else:
             if not isinstance(target, list):
                 target = [target]
             if self.fixed_name is not None:
                 lst = list(
                     filter(
                         lambda x: hasattr(x, "name") and getattr(
                             x, "name") == self.fixed_name, target))
                 if len(lst) > 0:
                     return lst[0], lookup_list, matched_path + [
                         lst[0]
                     ]  # return obj
                 else:
                     return None, lookup_list, matched_path  # return None
             else:
                 lst = list(
                     filter(
                         lambda x: hasattr(x, "name") and getattr(
                             x, "name") == lookup_list[0], target))
                 if len(lst) > 0:
                     return lst[0], lookup_list[1:], matched_path + [
                         lst[0]
                     ]  # return obj
                 else:
                     return None, lookup_list, matched_path  # return None
     else:
         return None, lookup_list, matched_path
Beispiel #3
0
 def custom_scope_redirection(obj):
     from textx import textx_isinstance
     if textx_isinstance(obj, mm["PackageRef"]):
         if obj.ref is None:
             from textx.scoping import Postponed
             return Postponed()
         return [obj.ref]
     else:
         return []
 def generic_scope_provider(obj, attr, attr_ref):
     if not obj.pyobj:
         from textx.scoping import Postponed
         return Postponed()
     if not hasattr(obj.pyobj, "data"):
         import json
         obj.pyobj.data = json.load(
             open(abspath(dirname(__file__)) + "/" + obj.pyobj.filename))
     if attr_ref.obj_name in obj.pyobj.data:
         return obj.pyobj.data[attr_ref.obj_name]
     else:
         raise Exception("{} not found".format(attr_ref.obj_name))
Beispiel #5
0
 def __call__(self, obj, attr, attr_ref):
     if attr.name == "pyobj":
         if attr_ref.obj_name in self.dict_with_objects:
             return self.dict_with_objects[attr_ref.obj_name]
         else:
             raise Exception("{} not found".format(attr_ref.obj_name))
     else:
         if not obj.pyobj:
             from textx.scoping import Postponed
             return Postponed()
         if hasattr(obj.pyobj, attr_ref.obj_name):
             return getattr(obj.pyobj, attr_ref.obj_name)
         else:
             raise Exception("{} not found".format(attr_ref.obj_name))
Beispiel #6
0
    def apply(self, obj, lookup_list, matched_path, first_element):
        """
        Args:
            obj: model object
            lookup_list: non-empty name list

        Returns:
            The object indicated by the navigation object,
            Postponed, None, or a list (if a list has to be processed).
        """
        from textx.scoping.tools import needs_to_be_resolved
        from textx.scoping import Postponed
        if first_element:
            from textx import get_model
            obj = get_model(obj)
        if len(lookup_list) == 0 and self.consume_name:
            return None, lookup_list, matched_path
        if needs_to_be_resolved(obj, self.name):
            return Postponed(), lookup_list, matched_path
        if hasattr(obj, self.name):
            target = getattr(obj, self.name)
            if not self.consume_name and self.fixed_name is None:
                return target, lookup_list, matched_path  # return list
            else:
                if not isinstance(target, list):
                    target = [target]
                if self.fixed_name is not None:
                    lst = list(
                        filter(
                            lambda x: hasattr(x, "name") and getattr(
                                x, "name") == self.fixed_name, target))
                    if len(lst) > 0:
                        return lst[0], lookup_list, matched_path + [
                            lst[0]
                        ]  # return obj
                    else:
                        return None, lookup_list, matched_path  # return None
                else:
                    lst = list(
                        filter(
                            lambda x: hasattr(x, "name") and getattr(
                                x, "name") == lookup_list[0], target))
                    if len(lst) > 0:
                        return lst[0], lookup_list[1:], matched_path + [
                            lst[0]
                        ]  # return obj
                    else:
                        return None, lookup_list, matched_path  # return None
        else:
            return None, lookup_list, matched_path
 def json_scope_provider(obj, attr, attr_ref):
     if not obj.pyobj:
         from textx.scoping import Postponed
         return Postponed()
     if not hasattr(obj.pyobj, "data"):
         import json
         obj.pyobj.data = json.load(
             open(
                 os.path.join(
                     os.path.abspath(
                         os.path.dirname(get_model(obj)._tx_filename)),
                     obj.pyobj.filename)))
     if attr_ref.obj_name in obj.pyobj.data:
         return obj.pyobj.data[attr_ref.obj_name]
     else:
         raise TextXSemanticError("{} not found".format(attr_ref.obj_name))
 def ref_scope(refItem, attr, attr_ref):
     from textx.scoping.tools import get_referenced_object
     from textx.scoping import Postponed
     reference = refItem.parent
     if reference is None:
         return Postponed()
     index = reference.refs.index(refItem)
     assert (index >= 0)
     if index == 0:
         return get_referenced_object(
             None, reference,
             "instance.type.vals.{}".format(attr_ref.obj_name),
             attr_ref.cls)
     else:
         return get_referenced_object(
             None, reference.refs[index - 1],
             "valref.type.vals.{}".format(attr_ref.obj_name), attr_ref.cls)
Beispiel #9
0
 def __call__(self, *args, **kwargs):
     ret = self.base(*args, **kwargs)
     if ret is None:
         return Postponed()
     else:
         return ret
Beispiel #10
0
def resolve_model_path(obj, dot_separated_name,
                       follow_named_element_in_lists=False):
    """
    Get a model object based on a model-path starting from some
    model object. It can be used in the same way you would
    navigate through a normal instance of a model object, except:
     - "parent(TYPE)" can be used to navigate to the parent of an
       element repeatedly, until a certain type is reached (see
       unittest).
     - lists of named objects (e.g. lists of named packages) can be
       traversed, as if the named objects were part of the model
       grammar (see unittest: Syntax,
       "name_of_model_list.name_of_named_obj_in_list").
     - None/Postponed values are intercepted and lead to an overall
       return value None/Postponed.
    A use case for this function is, when a model path needs to be
    stored and executed on a previously unknown object and/or the
    Postpone/None-logic is required.

    Args:
        obj: the current object
        dot_separated_name: the attribute name "a.b.c.d" starting from obj
           Note: the attribute "parent(TYPE)" is a shortcut to jump to the
           parent of type "TYPE" (exact match of type name).
        follow_named_element_in_lists: follow named elements in list if True
           override_unresolved_lists: try to follow unresolved lists, if True

    Returns:
        the object if found, or Postponed() if some postponed
        refs are found on the path / or obj is not found
    """
    from textx.scoping import Postponed
    names = dot_separated_name.split(".")
    match = re.match(r'parent\((\w+)\)', names[0])

    if obj is None or type(obj) is Postponed:
        return obj
    elif type(obj) is list:
        if follow_named_element_in_lists:
            next_obj = get_named_obj_in_list(obj, names[0])
        else:
            from textx.exceptions import TextXError
            raise TextXError(
                "unexpected: got list in path for get_referenced_object")
    elif match:
        next_obj = obj
        desired_parent_typename = match.group(1)
        next_obj = get_recursive_parent_with_typename(
            next_obj,
            desired_parent_typename)
        if type(next_obj) is Postponed:
            return next_obj
        elif next_obj is not None:
            return resolve_model_path(next_obj, ".".join(names[1:]),
                                      follow_named_element_in_lists)
        else:
            return None
    else:
        next_obj = getattr(obj, names[0])
        if needs_to_be_resolved(obj, names[0]):
            return Postponed()
        elif next_obj is None:
            return None
    if len(names) > 1:
        return resolve_model_path(next_obj, ".".join(
            names[1:]), follow_named_element_in_lists)
    return next_obj
Beispiel #11
0
def get_referenced_object(prev_obj,
                          obj,
                          dot_separated_name,
                          desired_type=None):
    """
    get objects based on a path

    Args:
        prev_obj: the object containing obj (req. is obj is a list)
        obj: the current object
        dot_separated_name: the attribute name "a.b.c.d" starting from obj
           Note: the attribute "parent(TYPE)" is a shortcut to jump to the
           parent of type "TYPE" (exact match of type name).
        desired_type: (optional)

    Returns:
        the object if found, None if not found or Postponed() if some postponed
        refs are found on the path
    """
    from textx.scoping import Postponed
    assert prev_obj or not type(obj) is list
    names = dot_separated_name.split(".")
    match = re.match(r'parent\((\w+)\)', names[0])
    if match:
        next_obj = obj
        desired_parent_typename = match.group(1)
        next_obj = get_recursive_parent_with_typename(next_obj,
                                                      desired_parent_typename)
        if next_obj:
            return get_referenced_object(None, next_obj, ".".join(names[1:]),
                                         desired_type)
        else:
            return None
    elif type(obj) is list:
        next_obj = None
        for res in obj:
            if hasattr(res, "name") and getattr(res, "name") == names[0]:
                if desired_type is None or textx_isinstance(res, desired_type):
                    next_obj = res
                else:
                    raise TypeError("{} has type {} instead of {}.".format(
                        names[0],
                        type(res).__name__, desired_type.__name__))
        if not next_obj:
            # if prev_obj needs to be resolved: return Postponed.
            if needs_to_be_resolved(prev_obj, names[0]):
                return Postponed()
            else:
                return None
    elif type(obj) is Postponed:
        return Postponed()
    else:
        next_obj = getattr(obj, names[0])
    if not next_obj:
        # if obj in in crossref return Postponed, else None
        if needs_to_be_resolved(obj, names[0]):
            return Postponed()
        else:
            return None
    if len(names) > 1:
        return get_referenced_object(obj, next_obj, ".".join(names[1:]),
                                     desired_type)
    if type(next_obj) is list and needs_to_be_resolved(obj, names[0]):
        return Postponed()
    return next_obj