diff options
author | root <devnull@localhost> | 2006-04-26 10:48:09 +0000 |
---|---|---|
committer | root <devnull@localhost> | 2006-04-26 10:48:09 +0000 |
commit | 8b1e1c104bdff504b3e775b450432e6462b8d09b (patch) | |
tree | 0367359f6a18f318741f387d82dc3dcfd8139950 /visitor.py | |
download | logilab-common-8b1e1c104bdff504b3e775b450432e6462b8d09b.tar.gz |
forget the past.
forget the past.
Diffstat (limited to 'visitor.py')
-rw-r--r-- | visitor.py | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/visitor.py b/visitor.py new file mode 100644 index 0000000..2fa42eb --- /dev/null +++ b/visitor.py @@ -0,0 +1,108 @@ +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +""" Copyright (c) 2002-2003 LOGILAB S.A. (Paris, FRANCE). + http://www.logilab.fr/ -- mailto:contact@logilab.fr + +a generic visitor abstract implementation +""" + +__revision__ = "$Id: visitor.py,v 1.14 2006-02-18 03:17:16 ludal Exp $" + +def no_filter(_): + return 1 + + +# Iterators ################################################################### +class FilteredIterator: + + 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: + + 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 begining 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) + + |