from .node import Node
from . import skipWhitespace, ParserError
from .gameRecord import GameRecord
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.parent = 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.parent = 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):
if len(self.nodes) == 0:
return None
for node in self.nodes[0].listGINodes():
yield GameRecord(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 moved from the seedNode.
def _buildSubtree(self, seedNode):
node = seedNode.copy()
node.setChildren(seedNode.children)
seedNode.children = []
while node.parent:
newNode = node.parent.copy()
newNode.addChild(node)
node = newNode
return node