else:
l_children.append(ch)
assert found, (self.children, self, new)
- self.parent.changed()
self.parent.children = l_children
+ self.parent.changed()
+ self.parent.invalidate_sibling_maps()
for x in new:
x.parent = self.parent
self.parent = None
return node.lineno
def changed(self):
+ if self.was_changed:
+ return
if self.parent:
self.parent.changed()
self.was_changed = True
if self.parent:
for i, node in enumerate(self.parent.children):
if node is self:
- self.parent.changed()
del self.parent.children[i]
+ self.parent.changed()
+ self.parent.invalidate_sibling_maps()
self.parent = None
return i
if self.parent is None:
return None
- # Can't use index(); we need to test by identity
- for i, child in enumerate(self.parent.children):
- if child is self:
- try:
- return self.parent.children[i+1]
- except IndexError:
- return None
+ if self.parent.next_sibling_map is None:
+ self.parent.update_sibling_maps()
+ return self.parent.next_sibling_map[id(self)]
@property
def prev_sibling(self):
if self.parent is None:
return None
- # Can't use index(); we need to test by identity
- for i, child in enumerate(self.parent.children):
- if child is self:
- if i == 0:
- return None
- return self.parent.children[i-1]
+ if self.parent.prev_sibling_map is None:
+ self.parent.update_sibling_maps()
+ return self.parent.prev_sibling_map[id(self)]
def leaves(self):
for child in self.children:
for ch in self.children:
assert ch.parent is None, repr(ch)
ch.parent = self
+ self.invalidate_sibling_maps()
if prefix is not None:
self.prefix = prefix
if fixers_applied:
self.children[i].parent = None
self.children[i] = child
self.changed()
+ self.invalidate_sibling_maps()
def insert_child(self, i, child):
"""
child.parent = self
self.children.insert(i, child)
self.changed()
+ self.invalidate_sibling_maps()
def append_child(self, child):
"""
child.parent = self
self.children.append(child)
self.changed()
-
+ self.invalidate_sibling_maps()
+
+ def invalidate_sibling_maps(self):
+ self.prev_sibling_map = None
+ self.next_sibling_map = None
+
+ def update_sibling_maps(self):
+ self.prev_sibling_map = _prev = {}
+ self.next_sibling_map = _next = {}
+ previous = None
+ for current in self.children:
+ _prev[id(current)] = previous
+ _next[id(previous)] = current
+ previous = current
+ _next[id(current)] = None
class Leaf(Base):
# Default values for instance variables
_prefix = "" # Whitespace and comments preceding this token in the input
lineno = 0 # Line where this token starts in the input
- column = 0 # Column where this token tarts in the input
+ column = 0 # Column where this token starts in the input
def __init__(self, type, value,
context=None,