| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
- # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
- #
- # This file is part of logilab-common.
- #
- # logilab-common is free software: you can redistribute it and/or modify it under
- # the terms of the GNU Lesser General Public License as published by the Free
- # Software Foundation, either version 2.1 of the License, or (at your option) any
- # later version.
- #
- # logilab-common is distributed in the hope that it will be useful, but WITHOUT
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- # details.
- #
- # You should have received a copy of the GNU Lesser General Public License along
- # with logilab-common. If not, see <http://www.gnu.org/licenses/>.
- """A generic visitor abstract implementation.
- """
- __docformat__ = "restructuredtext en"
- def no_filter(_):
- return 1
- # Iterators ###################################################################
- class FilteredIterator(object):
- def __init__(self, node, list_func, filter_func=None):
- self._next = [(node, 0)]
- if filter_func is None:
- filter_func = no_filter
- self._list = list_func(node, filter_func)
- def next(self):
- try:
- return self._list.pop(0)
- except :
- return None
- # Base Visitor ################################################################
- class Visitor(object):
- def __init__(self, iterator_class, filter_func=None):
- self._iter_class = iterator_class
- self.filter = filter_func
- def visit(self, node, *args, **kargs):
- """
- launch the visit on a given node
- call 'open_visit' before the beginning of the visit, with extra args
- given
- when all nodes have been visited, call the 'close_visit' method
- """
- self.open_visit(node, *args, **kargs)
- return self.close_visit(self._visit(node))
- def _visit(self, node):
- iterator = self._get_iterator(node)
- n = iterator.next()
- while n:
- result = n.accept(self)
- n = iterator.next()
- return result
- def _get_iterator(self, node):
- return self._iter_class(node, self.filter)
- def open_visit(self, *args, **kargs):
- """
- method called at the beginning of the visit
- """
- pass
- def close_visit(self, result):
- """
- method called at the end of the visit
- """
- return result
- # standard visited mixin ######################################################
- class VisitedMixIn(object):
- """
- Visited interface allow node visitors to use the node
- """
- def get_visit_name(self):
- """
- return the visit name for the mixed class. When calling 'accept', the
- method <'visit_' + name returned by this method> will be called on the
- visitor
- """
- try:
- return self.TYPE.replace('-', '_')
- except:
- return self.__class__.__name__.lower()
- def accept(self, visitor, *args, **kwargs):
- func = getattr(visitor, 'visit_%s' % self.get_visit_name())
- return func(self, *args, **kwargs)
- def leave(self, visitor, *args, **kwargs):
- func = getattr(visitor, 'leave_%s' % self.get_visit_name())
- return func(self, *args, **kwargs)
|