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