# HG changeset patch
# User Laman
# Date 2017-01-21 21:28:04
# Node ID 5781a5a0b2fb315b7b0050a12edd024734581ba2
# Parent  f0b8120281b98f6fa5d084ea91a6349fb78cb1fd

SGF nodes aware of their neighbours in the tree

diff --git a/src/sgfParser.py b/src/sgfParser.py
--- a/src/sgfParser.py
+++ b/src/sgfParser.py
@@ -1,10 +1,12 @@
 import re
 
+
 def skipWhitespace(s,start):
 	i=start
 	while i<len(s) and s[i].isspace(): i+=1
 	return i
 
+
 class Collection:
 	def __init__(self,s):
 		self.gameTrees=[]
@@ -19,7 +21,8 @@ class Collection:
 	def listGames(self):
 		for tree in self.gameTrees:
 			for game in tree.listGames(): yield game
-	
+
+
 class GameTree:
 	def __init__(self):
 		self.nodes=[]
@@ -36,14 +39,22 @@ class GameTree:
 		if x is None:
 			# print("error when parsing GameTree")
 			return (i,None)
+		y=None
 		while x is not None:
 			res.nodes.append(x)
+			if y: y.addChild(x)
+			x.setParent(y)
+			y=x
 			i=skipWhitespace(s,i)
 			i,x=Node.create(s,i)
 		i=skipWhitespace(s,i)
 		i,x=GameTree.create(s,i)
 		while x is not None:
 			res.branches.append(x)
+			subroot=x.getNode(0)
+			if subroot:
+				subroot.setParent(y)
+			if y: y.addChild(subroot)
 			i=skipWhitespace(s,i)
 			i,x=GameTree.create(s,i)
 		if s[i]!=")":
@@ -56,6 +67,11 @@ class GameTree:
 		for node in self._listGINodes():
 			yield self._buildSubtree(node)
 
+	def getNode(self,i):
+		if 0<=i<len(self.nodes):
+			return self.nodes[i]
+		return None
+
 	## Create and return a new GameTree containing the provided Node.
 	#
 	# The Node objects are shared between the trees, not copied.
@@ -73,10 +89,13 @@ class GameTree:
 		for tree in self.branches:
 			for node in tree._listGINodes():
 				yield node
-	
+
+
 class Node:
 	def __init__(self):
 		self.properties=dict()
+		self._parent=None
+		self._children=[]
 
 	@staticmethod
 	def create(s,start):
@@ -102,6 +121,27 @@ class Node:
 	def setProperty(self,name,value):
 		self.properties[name]=value
 		# zkontrolovat typ value
+
+	def setParent(self,node):
+		self._parent=node
+
+	def addChild(self,node):
+		if node in self._children: return node
+		self._children.append(node)
+		return node
+
+	def removeChild(self,node):
+		if node not in self._children:
+			return None
+		del self._children[self._children.index(node)]
+		return node
+
+	def removeChildAt(self,i):
+		if -len(self._children)<i<len(self._children):
+			res=self._children[i]
+			del self._children[i]
+			return res
+		return None
 		
 	def getProperty(self,name):
 		if name in self.properties: return self.properties[name]
@@ -126,6 +166,7 @@ class Property:
 		if x is None:
 			print('error when parsing property "{0}" at position {1}'.format(res.name,i))
 			return (start,None)
+		res.value=x
 		return (i,res)
 
 	@staticmethod
@@ -137,7 +178,7 @@ class Property:
 
 	@property
 	def type(self):
-		gameInfo=["AN","BR","BT","CP","DT","EV","GN","GC","ON","OT","PB","PC","PW","RE","RO","RU","SO","TM","US","WR","WT"]
+		gameInfo={"AN","BR","BT","CP","DT","EV","GN","GC","ON","OT","PB","PC","PW","RE","RO","RU","SO","TM","US","WR","WT"}
 		if self.name in gameInfo: return Property.GAME_INFO
 		else: return Property.UNKNOWN