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. if 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 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
get objects based on a path

    Args:
        prev_obj: the object containing obj (req. if 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