Files @ b9d29dcfe3d8
Branch filter:

Location: Diana/src/sgfParser/collection.py

Laman
svg rendering
from sgfParser.node import Node
from . import skipWhitespace, ParserError


class Collection:
	def __init__(self,s):
		self.gameTrees=[]
		i=skipWhitespace(s,0)
		if i>=len(s): return
		elif not GameTree.fits(s,i):
			raise ParserError("expected a GameTree starting with '('",s,i)
		while GameTree.fits(s,i):
			i,x=GameTree.create(s,i)
			self.gameTrees.append(x)
		if i<len(s):
			raise ParserError("expected EOF",s,i)

	def listGames(self):
		for tree in self.gameTrees:
			for game in tree.listGames(): yield game


class GameTree:
	def __init__(self):
		self.nodes=[]
		self.branches=[]

	@staticmethod
	def fits(s,i):
		return i<len(s) and s[i]=="("

	@staticmethod
	def create(s,start):
		assert GameTree.fits(s,start)
		res=GameTree()

		i=skipWhitespace(s,start+1)
		if not Node.fits(s,i):
			raise ParserError("expected a Node starting with ';'",s,i)

		y=None
		while Node.fits(s,i):
			i,x=Node.create(s,i)
			res.nodes.append(x)
			if y: y.addChild(x)
			x.setParent(y)
			y=x
			i=skipWhitespace(s,i)

		while GameTree.fits(s,i):
			i,x=GameTree.create(s,i)
			res.branches.append(x)
			subroot=x.getNode(0)
			subroot.setParent(y)
			if y: y.addChild(subroot)
			i=skipWhitespace(s,i)
		if i>=len(s) or s[i]!=")":
			raise ParserError("expected end of a GameTree marked by ')'",s,i)
		i=skipWhitespace(s,i+1)
		return (i,res)

	## Expand multiple games into distinct GameTrees and yield each.
	def listGames(self):
		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 game tree containing the provided Node.
	#
	# Ancestor nodes are copied, descendants are shared.
	def _buildSubtree(self,seedNode):
		node=seedNode.copy()

		while node.parent:
			newNode=node.parent.copy()
			node.parent=newNode
			newNode.setChildren([node])
			node=newNode

		return node

	## Find and yield Game Info nodes.
	def _listGINodes(self):
		for node in self.nodes:
			if node.isGINode():
				yield node
		for tree in self.branches:
			for node in tree._listGINodes():
				yield node