Files
@ d57d0d4ede15
Branch filter:
Location: Diana/src/diana/sgfParser/node.py - annotation
d57d0d4ede15
3.2 KiB
text/x-python
changed the naming convention to follow standards
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 616c96178973 36b0271e7393 616c96178973 d57d0d4ede15 616c96178973 616c96178973 616c96178973 616c96178973 616c96178973 686166c7d5bc 686166c7d5bc 686166c7d5bc 616c96178973 616c96178973 686166c7d5bc 686166c7d5bc 616c96178973 616c96178973 686166c7d5bc 686166c7d5bc 686166c7d5bc 616c96178973 d57d0d4ede15 686166c7d5bc 686166c7d5bc 616c96178973 686166c7d5bc 616c96178973 686166c7d5bc d57d0d4ede15 686166c7d5bc 616c96178973 d57d0d4ede15 d57d0d4ede15 686166c7d5bc d57d0d4ede15 616c96178973 686166c7d5bc 616c96178973 686166c7d5bc d57d0d4ede15 686166c7d5bc 616c96178973 616c96178973 686166c7d5bc 686166c7d5bc 686166c7d5bc d57d0d4ede15 686166c7d5bc 616c96178973 616c96178973 686166c7d5bc 686166c7d5bc 616c96178973 d57d0d4ede15 686166c7d5bc 616c96178973 d57d0d4ede15 686166c7d5bc 686166c7d5bc 616c96178973 d57d0d4ede15 686166c7d5bc 686166c7d5bc 686166c7d5bc 616c96178973 d57d0d4ede15 686166c7d5bc 686166c7d5bc 686166c7d5bc 616c96178973 616c96178973 616c96178973 d57d0d4ede15 616c96178973 616c96178973 616c96178973 686166c7d5bc 616c96178973 616c96178973 d57d0d4ede15 686166c7d5bc 686166c7d5bc 616c96178973 686166c7d5bc 616c96178973 616c96178973 616c96178973 616c96178973 616c96178973 686166c7d5bc 686166c7d5bc 686166c7d5bc 616c96178973 616c96178973 d57d0d4ede15 686166c7d5bc 686166c7d5bc 686166c7d5bc 686166c7d5bc 616c96178973 616c96178973 616c96178973 616c96178973 616c96178973 616c96178973 e3e6dfbb44f6 686166c7d5bc 686166c7d5bc 616c96178973 686166c7d5bc 686166c7d5bc 686166c7d5bc 686166c7d5bc e3e6dfbb44f6 616c96178973 d57d0d4ede15 d57d0d4ede15 e3e6dfbb44f6 d57d0d4ede15 686166c7d5bc 686166c7d5bc 616c96178973 d57d0d4ede15 686166c7d5bc 616c96178973 616c96178973 | from collections import deque
import logging as log
from . import skip_whitespace, ParserWarning
from .property import Property, GAME_INFO
class Node:
def __init__(self):
self.properties = dict()
self.parent = None
self.children = []
@staticmethod
def fits(s, i):
return i < len(s) and s[i] == ";"
@staticmethod
def create(s, start):
assert Node.fits(s, start)
res = Node()
i = skip_whitespace(s, start + 1)
while Property.fits(s, i):
(i, x) = Property.create(s, i)
if x.name in res.properties:
log.warning(ParserWarning('duplicate "{0}" property in a node. second value ignored'.format(x.name), s, i))
else:
res.properties[x.name] = x
i = skip_whitespace(s, i)
return (i, res)
def list_gi_nodes(self):
if self.is_gi_node():
yield self
empty = not self.is_gi_node()
node = self
while node.parent:
node = node.parent
if node.is_gi_node():
empty = False
yield node
queue = deque(self.children)
while len(queue) > 0:
node = queue.popleft()
if node.is_gi_node():
empty = False
yield node
queue.extend(node.children)
if empty:
yield self # always yield at least self, can work as GINode as well as any other
def is_gi_node(self):
return any(prop.type == GAME_INFO for prop in self.properties.values())
def set_prop(self, name, value):
self.properties[name] = value
# check value type
def set_children(self, children):
self.children = children
for child in children:
child.parent = self
def add_child(self, node):
if node in self.children:
return node
node.parent = self
self.children.append(node)
return node
def remove_child(self, node):
if node not in self.children:
return None
del self.children[self.children.index(node)]
node.parent = None
return node
def remove_child_at(self, i):
if -len(self.children) < i < len(self.children):
res = self.children[i]
del self.children[i]
res.parent = None
return res
return None
## Create a copy of the Node, with the same parent and deep copied properties, no copied children.
def copy(self):
res = Node()
res.properties = {k: v.copy() for (k, v) in self.properties.items()}
res.parent = self.parent
return res
def get_prop(self, name, default=None):
if name in self.properties:
return self.properties[name].value
else:
return default
## Returns textual representation of the Node itself, but disregards its children.
def __str__(self):
return ";" + "".join(str(p) for p in self.properties.values())
def export(self):
# there is a beautiful recursive solution, which this stack is too narrow to contain
stack = [(self, 1, 1)]
output = []
while len(stack) > 0:
(node, left, right) = stack.pop()
if left > 0:
output.append("("*left)
output.append(str(node)+"\n")
child_count = len(node.children)
if child_count == 0: # a leaf
output.append(")"*right+"\n")
elif child_count == 1: # a line
stack.append((node.children[0], 0, right))
else: # a branching node
# first child pops first, last child closes parent's parentheses
children = zip(node.children, [1]*child_count, [1]*(child_count-1)+[1+right])
stack.extend(reversed(list(children)))
return "".join(output)
|