Changeset - f90261363a85
[Not reviewed]
default
1 4 0
Laman - 9 years ago 2016-08-14 08:55:54

spaces to tabs
5 files changed with 1053 insertions and 1177 deletions:
diana.py
170
170
go.py
29
29
sgf.py
451
451
sgfParser.py
403
403
0 comments (0 inline, 0 general)
diana.py
Show inline comments
 
@@ -5,9 +5,9 @@ import os
 
import sgf
 
 
if len(sys.argv)>1:
 
  files=sys.argv[1:]
 
	files=sys.argv[1:]
 
else:
 
  sys.exit("no input file specified")
 
	sys.exit("no input file specified")
 
 
movesPerDiagram=75
 
minMovesPerDiagram=10
 
@@ -18,190 +18,190 @@ padding=15
 
highNumbers=True
 
 
class Svg:
 
  content=""
 
  footer=""
 
  extension="svg"
 
	content=""
 
	footer=""
 
	extension="svg"
 
 
  padding=15
 
  gridSize=28
 
  highNumbers=True
 
  
 
  def __init__(self):
 
    self.content='''<?xml version="1.0" standalone="no"?>
 
	padding=15
 
	gridSize=28
 
	highNumbers=True
 
	
 
	def __init__(self):
 
		self.content='''<?xml version="1.0" standalone="no"?>
 
<svg width="{0}" height="{0}" version="1.1" xmlns="http://www.w3.org/2000/svg" alignment-baseline="center">
 
  <defs>
 
    <style type="text/css"><![CDATA[
 
    text{{font-family:"DejaVu Sans";text-anchor:middle;}}
 
    line{{stroke:black;stroke-width:0.7}}
 
    circle{{stroke:black}}
 
    .b{{fill:black}}
 
    .w{{fill:white}}
 
    ]]></style>
 
  </defs>
 
  <rect width="{0}" height="{0}" x="0" y="0" style="fill:white;stroke:white"/>\n'''.format(2*self.padding+18*self.gridSize)
 
    self.footer="</svg>\n"
 
	<defs>
 
		<style type="text/css"><![CDATA[
 
		text{{font-family:"DejaVu Sans";text-anchor:middle;}}
 
		line{{stroke:black;stroke-width:0.7}}
 
		circle{{stroke:black}}
 
		.b{{fill:black}}
 
		.w{{fill:white}}
 
		]]></style>
 
	</defs>
 
	<rect width="{0}" height="{0}" x="0" y="0" style="fill:white;stroke:white"/>\n'''.format(2*self.padding+18*self.gridSize)
 
		self.footer="</svg>\n"
 
 
    grid='  <line x1="{0}" x2="{1}" y1="{2}" y2="{3}" />\n'
 
		grid='  <line x1="{0}" x2="{1}" y1="{2}" y2="{3}" />\n'
 
 
    # okraje desky
 
    for i in (0,18):
 
      self.content+='  <line x1="{0}" x2="{1}" y1="{2}" y2="{3}" style="stroke-width:1"/>\n'.format(self.padding, 18*self.gridSize+self.padding, self.gridSize*i+self.padding, self.gridSize*i+self.padding)
 
      self.content+='  <line x1="{0}" x2="{1}" y1="{2}" y2="{3}" style="stroke-width:1"/>\n'.format(self.gridSize*i+self.padding, self.gridSize*i+self.padding, self.padding, 18*self.gridSize+self.padding)
 
    
 
    # mřížka
 
    for i in range(1,18):
 
      self.content+=grid.format(padding, 18*c+padding, c*i+padding, c*i+padding)
 
      self.content+=grid.format(c*i+padding, c*i+padding, padding, 18*c+padding)
 
		# okraje desky
 
		for i in (0,18):
 
			self.content+='  <line x1="{0}" x2="{1}" y1="{2}" y2="{3}" style="stroke-width:1"/>\n'.format(self.padding, 18*self.gridSize+self.padding, self.gridSize*i+self.padding, self.gridSize*i+self.padding)
 
			self.content+='  <line x1="{0}" x2="{1}" y1="{2}" y2="{3}" style="stroke-width:1"/>\n'.format(self.gridSize*i+self.padding, self.gridSize*i+self.padding, self.padding, 18*self.gridSize+self.padding)
 
		
 
		# mřížka
 
		for i in range(1,18):
 
			self.content+=grid.format(padding, 18*c+padding, c*i+padding, c*i+padding)
 
			self.content+=grid.format(c*i+padding, c*i+padding, padding, 18*c+padding)
 
 
    # hvězdy
 
    for i in range(3):
 
      for j in range(3):
 
        self.content+='  <circle cx="{0}" cy="{1}" r="{2}" class="b"/>\n'.format(padding+3*c+6*i*c, padding+3*c+6*j*c, 2)
 
  
 
  def __str__(self):
 
    return self.content+self.footer
 
          
 
  def drawStone(self,x,y,color):
 
    self.content+='  <circle cx="{0}" cy="{1}" r="{2}" class="{3}" />\n'.format(padding+x*c, padding+y*c, c/2-1, color)
 
		# hvězdy
 
		for i in range(3):
 
			for j in range(3):
 
				self.content+='  <circle cx="{0}" cy="{1}" r="{2}" class="b"/>\n'.format(padding+3*c+6*i*c, padding+3*c+6*j*c, 2)
 
	
 
	def __str__(self):
 
		return self.content+self.footer
 
					
 
	def drawStone(self,x,y,color):
 
		self.content+='  <circle cx="{0}" cy="{1}" r="{2}" class="{3}" />\n'.format(padding+x*c, padding+y*c, c/2-1, color)
 
 
  def getFontSize(self,text):
 
    if len(text)<2: return round(0.7*c)
 
    elif len(text)<3: return round(0.55*c)
 
    else: return round(0.4*c)
 
	def getFontSize(self,text):
 
		if len(text)<2: return round(0.7*c)
 
		elif len(text)<3: return round(0.55*c)
 
		else: return round(0.4*c)
 
 
  def writeLabel(self,x,y,label,color):
 
    label=str(label)
 
    fontSize=self.getFontSize(label)
 
    self.content+='  <text x="{0}" y="{1}" class="{2}" font-size="{3}">{4}</text>\n'.format(padding+x*c, padding+y*c+0.35*fontSize, color, fontSize, label)
 
    
 
  def drawMove(self,x,y,label,color):
 
    labelColor="w" if color=="b" else "b"
 
    
 
    if (not self.highNumbers) and isinstance(label,int) and label%100!=0: label=label%100 # dost neobratná logika
 
    
 
    self.drawStone(x,y,color)
 
    self.writeLabel(x,y,label,labelColor)
 
    
 
  def getContent(self):
 
    return self.content+self.footer
 
	def writeLabel(self,x,y,label,color):
 
		label=str(label)
 
		fontSize=self.getFontSize(label)
 
		self.content+='  <text x="{0}" y="{1}" class="{2}" font-size="{3}">{4}</text>\n'.format(padding+x*c, padding+y*c+0.35*fontSize, color, fontSize, label)
 
		
 
	def drawMove(self,x,y,label,color):
 
		labelColor="w" if color=="b" else "b"
 
		
 
		if (not self.highNumbers) and isinstance(label,int) and label%100!=0: label=label%100 # dost neobratná logika
 
		
 
		self.drawStone(x,y,color)
 
		self.writeLabel(x,y,label,labelColor)
 
		
 
	def getContent(self):
 
		return self.content+self.footer
 
 
 
class Tikz:
 
  content=""
 
  footer=""
 
  extension="tex"
 
  
 
  highNumbers=True
 
  
 
  def __init__(self):
 
    self.content=r'''\begin{tikzpicture}
 
  \draw[step=\boardSquare,gray,very thin] (0,0) grid (18\boardSquare,18\boardSquare);
 
  \draw (0,0) rectangle (18\boardSquare,18\boardSquare);
 
  
 
  '''
 
    
 
    # hvězdy
 
    for i in range(3):
 
      for j in range(3):
 
        self.content+=r'''  \filldraw[fill=black] ({0}\boardSquare,{1}\boardSquare) circle[radius=0.04];'''.format(6*i+3, 6*j+3)+'\n'
 
      self.content+='\n'
 
  
 
    self.footer=r'\end{tikzpicture}' '\n'
 
      
 
  def __str__(self):
 
    return self.content+self.footer
 
	content=""
 
	footer=""
 
	extension="tex"
 
	
 
	highNumbers=True
 
	
 
	def __init__(self):
 
		self.content=r'''\begin{tikzpicture}
 
	\draw[step=\boardSquare,gray,very thin] (0,0) grid (18\boardSquare,18\boardSquare);
 
	\draw (0,0) rectangle (18\boardSquare,18\boardSquare);
 
	
 
	'''
 
		
 
		# hvězdy
 
		for i in range(3):
 
			for j in range(3):
 
				self.content+=r'''  \filldraw[fill=black] ({0}\boardSquare,{1}\boardSquare) circle[radius=0.04];'''.format(6*i+3, 6*j+3)+'\n'
 
			self.content+='\n'
 
	
 
		self.footer=r'\end{tikzpicture}' '\n'
 
			
 
	def __str__(self):
 
		return self.content+self.footer
 
 
  def drawStone(self,x,y,color):
 
    fill="black" if color=="b" else "white"
 
    self.content+=r'  \filldraw[draw=black,fill={0}] ({1}\boardSquare,{2}\boardSquare) circle[radius=0.5\boardSquare];'.format(fill,x,18-y)+'\n'
 
  
 
  def drawMove(self,x,y,label,color):
 
    fill="black" if color=="b" else "white"
 
    labelColor="white" if color=="b" else "black"
 
    if (not self.highNumbers) and isinstance(label,int) and label%100!=0: label=label%100 # dost neobratná logika
 
    
 
    self.content+=r'  \filldraw[draw=black,fill={0}] ({1}\boardSquare,{2}\boardSquare) circle[radius=0.5\boardSquare] node[color={3}]{{{4}}};'.format(fill,x,18-y,labelColor,label)+'\n'
 
    
 
  def getContent(self):
 
    return self.content+self.footer
 
	def drawStone(self,x,y,color):
 
		fill="black" if color=="b" else "white"
 
		self.content+=r'  \filldraw[draw=black,fill={0}] ({1}\boardSquare,{2}\boardSquare) circle[radius=0.5\boardSquare];'.format(fill,x,18-y)+'\n'
 
	
 
	def drawMove(self,x,y,label,color):
 
		fill="black" if color=="b" else "white"
 
		labelColor="white" if color=="b" else "black"
 
		if (not self.highNumbers) and isinstance(label,int) and label%100!=0: label=label%100 # dost neobratná logika
 
		
 
		self.content+=r'  \filldraw[draw=black,fill={0}] ({1}\boardSquare,{2}\boardSquare) circle[radius=0.5\boardSquare] node[color={3}]{{{4}}};'.format(fill,x,18-y,labelColor,label)+'\n'
 
		
 
	def getContent(self):
 
		return self.content+self.footer
 
 
 
def processFile(fileName):
 
  shortName="".join(re.split(r'[/\\]',fileName)[-1].split('.')[:-1])
 
  
 
  game=go.Go()
 
  global t
 
  
 
  record=sgf.Sgf(open(fileName,'r',encoding="utf-8").read())
 
  moves=record.getMoves()
 
	shortName="".join(re.split(r'[/\\]',fileName)[-1].split('.')[:-1])
 
	
 
	game=go.Go()
 
	global t
 
	
 
	record=sgf.Sgf(open(fileName,'r',encoding="utf-8").read())
 
	moves=record.getMoves()
 
 
  localBoard=dict()
 
  overlays=""
 
  letters=dict()
 
  letter='a'
 
	localBoard=dict()
 
	overlays=""
 
	letters=dict()
 
	letter='a'
 
 
  diagramsNeeded=(len(moves)-minMovesPerDiagram)//movesPerDiagram+1
 
  moveNumber=0
 
  
 
  for i in range(diagramsNeeded):
 
    # inicializuj diagram
 
    diagram=Tikz()
 
    
 
    for lineNumber,line in enumerate(game.board):
 
      for itemNumber,item in enumerate(line):
 
        if item==1: diagram.drawStone(itemNumber,lineNumber,"b")
 
        if item==-1: diagram.drawStone(itemNumber,lineNumber,"w")
 
      localBoard={(a,b):game.board[b][a]-1 for a in range(19) for b in range(19) if game.board[b][a]!=0}
 
    
 
    for j in range(movesPerDiagram):
 
      # kresli tahy
 
      if moveNumber>=len(moves): break
 
      
 
      c,(x,y)=moves[moveNumber]
 
      c=c.lower()
 
      
 
      if not game.move(1 if c=='b' else -1,x,y):
 
        print("illegal move: {0} at {1},{2}".format(moveNumber+1,x,y))
 
        moveNumber+=1
 
        continue
 
      
 
      # zapíšu tah na volný průsečík
 
      if not (x,y) in localBoard:
 
        localBoard[(x,y)]=moveNumber+1
 
        diagram.drawMove(x,y,moveNumber+1,c)
 
      # průsečík je obsazený nepopsaným kamenem
 
      elif localBoard[(x,y)]<1:
 
        # průsečík není popsaný ani písmenem
 
        if not (x,y) in letters:
 
          letters[(x,y)]=letter
 
          color='b' if localBoard[(x,y)]==0 else 'w'
 
          diagram.drawMove(x,y,letter,color)
 
          letter=chr(ord(letter)+1)
 
        overlays+="{0} = {1}\n".format(moveNumber+1,letters[(x,y)])
 
      # průsečík je obsazený očíslovaným kamenem
 
      else: overlays+="{0} = {1}\n".format(moveNumber+1,localBoard[(x,y)])
 
      
 
      moveNumber+=1
 
      
 
    # dokonči a ulož diagram
 
	diagramsNeeded=(len(moves)-minMovesPerDiagram)//movesPerDiagram+1
 
	moveNumber=0
 
	
 
	for i in range(diagramsNeeded):
 
		# inicializuj diagram
 
		diagram=Tikz()
 
		
 
		for lineNumber,line in enumerate(game.board):
 
			for itemNumber,item in enumerate(line):
 
				if item==1: diagram.drawStone(itemNumber,lineNumber,"b")
 
				if item==-1: diagram.drawStone(itemNumber,lineNumber,"w")
 
			localBoard={(a,b):game.board[b][a]-1 for a in range(19) for b in range(19) if game.board[b][a]!=0}
 
		
 
		for j in range(movesPerDiagram):
 
			# kresli tahy
 
			if moveNumber>=len(moves): break
 
			
 
			c,(x,y)=moves[moveNumber]
 
			c=c.lower()
 
			
 
			if not game.move(1 if c=='b' else -1,x,y):
 
				print("illegal move: {0} at {1},{2}".format(moveNumber+1,x,y))
 
				moveNumber+=1
 
				continue
 
			
 
			# zapíšu tah na volný průsečík
 
			if not (x,y) in localBoard:
 
				localBoard[(x,y)]=moveNumber+1
 
				diagram.drawMove(x,y,moveNumber+1,c)
 
			# průsečík je obsazený nepopsaným kamenem
 
			elif localBoard[(x,y)]<1:
 
				# průsečík není popsaný ani písmenem
 
				if not (x,y) in letters:
 
					letters[(x,y)]=letter
 
					color='b' if localBoard[(x,y)]==0 else 'w'
 
					diagram.drawMove(x,y,letter,color)
 
					letter=chr(ord(letter)+1)
 
				overlays+="{0} = {1}\n".format(moveNumber+1,letters[(x,y)])
 
			# průsečík je obsazený očíslovaným kamenem
 
			else: overlays+="{0} = {1}\n".format(moveNumber+1,localBoard[(x,y)])
 
			
 
			moveNumber+=1
 
			
 
		# dokonči a ulož diagram
 
	# TODO rozumně pracovat s adresáři
 
    t=open(os.path.join(os.path.dirname(__file__),"out","{0}-{1}.{2}".format(shortName,i+1,diagram.extension)),'w') # nový soubor
 
    t.write(diagram.getContent())
 
    t.close()
 
      
 
  notes=open(os.path.join(os.path.dirname(__file__),"out","{0}.txt".format(shortName)),'w')
 
  notes.write(overlays)
 
  notes.close()
 
  
 
		t=open(os.path.join(os.path.dirname(__file__),"out","{0}-{1}.{2}".format(shortName,i+1,diagram.extension)),'w') # nový soubor
 
		t.write(diagram.getContent())
 
		t.close()
 
			
 
	notes=open(os.path.join(os.path.dirname(__file__),"out","{0}.txt".format(shortName)),'w')
 
	notes.write(overlays)
 
	notes.close()
 
	
 
print("processing:")
 
for item in files:
 
  # relativně vůči work directory nebo vůči skriptu?
 
  # item=os.path.join(os.path.dirname(__file__),item)
 
  if os.path.isfile(item):
 
    print("{0}... ".format(item),end="")
 
    processFile(item)
 
    print("done")
 
  elif os.path.isdir(item):
 
    files+=[os.path.join(item,child) for child in os.listdir(item)]
 
    print("contents of the '{0}' directory added to the queue".format(item))
 
  else: print("the '{0}' path could not be resolved to either a file nor a directory".format(item))
 
	# relativně vůči work directory nebo vůči skriptu?
 
	# item=os.path.join(os.path.dirname(__file__),item)
 
	if os.path.isfile(item):
 
		print("{0}... ".format(item),end="")
 
		processFile(item)
 
		print("done")
 
	elif os.path.isdir(item):
 
		files+=[os.path.join(item,child) for child in os.listdir(item)]
 
		print("contents of the '{0}' directory added to the queue".format(item))
 
	else: print("the '{0}' path could not be resolved to either a file nor a directory".format(item))
go.py
Show inline comments
 
class Go:
 
  # 1: B, 0: _, -1: W
 
  # resp. jakákoli čísla s opačnými znaménky
 
  board=[[0]*19 for i in range(19)]
 
  
 
  def __init__(self): self.board=[[0]*19 for i in range(19)]
 
  
 
  def move(self,color,y,x):
 
    if self.board[x][y]!=0: return False
 
	# 1: B, 0: _, -1: W
 
	# resp. jakákoli čísla s opačnými znaménky
 
	board=[[0]*19 for i in range(19)]
 
	
 
	def __init__(self): self.board=[[0]*19 for i in range(19)]
 
	
 
	def move(self,color,y,x):
 
		if self.board[x][y]!=0: return False
 
 
    self.board[x][y]=color
 
		self.board[x][y]=color
 
 
    for i,j in ((-1,0),(1,0),(0,-1),(0,1)):
 
      self.temp=[[False]*19 for i in range(19)]
 
      if not self._floodFill(-color,x+i,y+j): self._remove()
 
    self.temp=[[False]*19 for i in range(19)]
 
    if not self._floodFill(color,x,y):
 
      self.board[x][y]=0
 
      return False
 
    return True
 
		for i,j in ((-1,0),(1,0),(0,-1),(0,1)):
 
			self.temp=[[False]*19 for i in range(19)]
 
			if not self._floodFill(-color,x+i,y+j): self._remove()
 
		self.temp=[[False]*19 for i in range(19)]
 
		if not self._floodFill(color,x,y):
 
			self.board[x][y]=0
 
			return False
 
		return True
 
 
  def _floodFill(self,color,x,y):
 
    if x<0 or x>18 or y<0 or y>18: return False
 
    if self.temp[x][y]: return False
 
    if self.board[x][y]==0: return True
 
    if self.board[x][y]!=color: return False
 
    self.temp[x][y]=True
 
    return self._floodFill(color,x-1,y) or self._floodFill(color,x+1,y) or self._floodFill(color,x,y-1) or self._floodFill(color,x,y+1)
 
  
 
  def _remove(self):
 
    for i in range(19):
 
      for j in range(19):
 
        if self.temp[i][j]: self.board[i][j]=0
 
	def _floodFill(self,color,x,y):
 
		if x<0 or x>18 or y<0 or y>18: return False
 
		if self.temp[x][y]: return False
 
		if self.board[x][y]==0: return True
 
		if self.board[x][y]!=color: return False
 
		self.temp[x][y]=True
 
		return self._floodFill(color,x-1,y) or self._floodFill(color,x+1,y) or self._floodFill(color,x,y-1) or self._floodFill(color,x,y+1)
 
	
 
	def _remove(self):
 
		for i in range(19):
 
			for j in range(19):
 
				if self.temp[i][j]: self.board[i][j]=0
sgf-compresor.py
Show inline comments
 
deleted file
sgf.py
Show inline comments
 
@@ -2,493 +2,493 @@
 
 
 
class Collection:
 
  gameTrees=[]
 
  
 
  def export(self):
 
    res=""
 
    for root in gameTrees:
 
      res+="({0})\n".format(root.fullExport())
 
    return res
 
  
 
	gameTrees=[]
 
	
 
	def export(self):
 
		res=""
 
		for root in gameTrees:
 
			res+="({0})\n".format(root.fullExport())
 
		return res
 
	
 
class Node:
 
  parent=None
 
  children=[]
 
  properties={}
 
  
 
  def newChild(self):
 
    child=Node()
 
    child.parent=self
 
    self.children.append(child)
 
    return child
 
    
 
  def addChild(self,child):
 
    child.parent=self
 
    self.children.append(child)
 
    
 
  def delChild(self,index):
 
    del self.children[index]
 
    
 
  def setProperty(self): pass
 
  def getProperty(self): pass
 
  
 
  def fullExport(self):
 
    res=self.export()
 
    if len(self.children)==1: res+=children[0].fullExport()
 
    else:
 
      for child in self.children:
 
        res+=child.fullExport()
 
    return res
 
      
 
  def export(self):
 
    res=";"
 
    for name,value in properties.items():
 
      res+="{0}[{1}]".format(name,value) # !! str(value)
 
    res+="\n"
 
    return res
 
    
 
	parent=None
 
	children=[]
 
	properties={}
 
	
 
	def newChild(self):
 
		child=Node()
 
		child.parent=self
 
		self.children.append(child)
 
		return child
 
		
 
	def addChild(self,child):
 
		child.parent=self
 
		self.children.append(child)
 
		
 
	def delChild(self,index):
 
		del self.children[index]
 
		
 
	def setProperty(self): pass
 
	def getProperty(self): pass
 
	
 
	def fullExport(self):
 
		res=self.export()
 
		if len(self.children)==1: res+=children[0].fullExport()
 
		else:
 
			for child in self.children:
 
				res+=child.fullExport()
 
		return res
 
			
 
	def export(self):
 
		res=";"
 
		for name,value in properties.items():
 
			res+="{0}[{1}]".format(name,value) # !! str(value)
 
		res+="\n"
 
		return res
 
		
 
class Property:
 
  name=""
 
  value=None
 
	name=""
 
	value=None
 
 
class ListOf(Property):
 
  values=[]
 
  vType=None
 
	values=[]
 
	vType=None
 
 
  def __str__(self):
 
    return "["+"][".join(self.values)+"]"
 
    
 
	def __str__(self):
 
		return "["+"][".join(self.values)+"]"
 
		
 
class Composed(Property):
 
  value=()
 
  
 
  def __str__(self):
 
    return self.value[0]+":"+self.value[1] # !! str(self.value[0])
 
	value=()
 
	
 
	def __str__(self):
 
		return self.value[0]+":"+self.value[1] # !! str(self.value[0])
 
 
class Point(Property): # !! pass
 
  row=0
 
  col=0
 
  
 
  def __str__(self):
 
    f=lambda x: chr(x+ord("a")) if x<26 else chr(x-26+ord("A"))
 
    row=f(self.row)
 
    col=f(self.col)
 
    
 
    return col+row
 
    
 
	row=0
 
	col=0
 
	
 
	def __str__(self):
 
		f=lambda x: chr(x+ord("a")) if x<26 else chr(x-26+ord("A"))
 
		row=f(self.row)
 
		col=f(self.col)
 
		
 
		return col+row
 
		
 
 
  
 
	
 
def skipWhitespace(str,start):
 
  i=start
 
  while i<len(str) and str[i].isspace(): i+=1
 
  return i
 
	i=start
 
	while i<len(str) and str[i].isspace(): i+=1
 
	return i
 
 
class Collection:
 
  gameTrees=[]
 
  
 
  def __init__(self,str):
 
    self.gameTrees=[]
 
    i,x=GameTree.create(str,0)
 
    if x is None:
 
      print("error when parsing Collection")
 
      return
 
    while x is not None:
 
      self.gameTrees.append(x)
 
      i,x=GameTree.create(str,i)
 
  
 
	gameTrees=[]
 
	
 
	def __init__(self,str):
 
		self.gameTrees=[]
 
		i,x=GameTree.create(str,0)
 
		if x is None:
 
			print("error when parsing Collection")
 
			return
 
		while x is not None:
 
			self.gameTrees.append(x)
 
			i,x=GameTree.create(str,i)
 
	
 
class GameTree:
 
  nodes=[]
 
  branches=[]
 
    
 
  def create(str,start):
 
    res=GameTree()
 
    i=skipWhitespace(str,start)
 
    if i>=len(str) or str[i]!="(":
 
      # print("error when parsing GameTree")
 
      return (start,None)
 
    i=skipWhitespace(str,i)
 
    i,x=Node.create(str,start+1)
 
    if x is None:
 
      # print("error when parsing GameTree")
 
      return (i,None)
 
    while x is not None:
 
      res.nodes.append(x)
 
      i=skipWhitespace(str,i)
 
      i,x=Node.create(str,i)
 
    i=skipWhitespace(str,i)
 
    i,x=GameTree.create(str,i)
 
    while x is not None:
 
      res.branches.append(x)
 
      i=skipWhitespace(str,i)
 
      i,x=GameTree.create(str,i)
 
    if str[i]!=")":
 
      # print("error when parsing GameTree")
 
      return (i,None)
 
    return (i+1,res)
 
  
 
	nodes=[]
 
	branches=[]
 
		
 
	def create(str,start):
 
		res=GameTree()
 
		i=skipWhitespace(str,start)
 
		if i>=len(str) or str[i]!="(":
 
			# print("error when parsing GameTree")
 
			return (start,None)
 
		i=skipWhitespace(str,i)
 
		i,x=Node.create(str,start+1)
 
		if x is None:
 
			# print("error when parsing GameTree")
 
			return (i,None)
 
		while x is not None:
 
			res.nodes.append(x)
 
			i=skipWhitespace(str,i)
 
			i,x=Node.create(str,i)
 
		i=skipWhitespace(str,i)
 
		i,x=GameTree.create(str,i)
 
		while x is not None:
 
			res.branches.append(x)
 
			i=skipWhitespace(str,i)
 
			i,x=GameTree.create(str,i)
 
		if str[i]!=")":
 
			# print("error when parsing GameTree")
 
			return (i,None)
 
		return (i+1,res)
 
	
 
class Node:
 
  properties=dict()
 
  
 
  def create(str,start):
 
    res=Node()
 
    if str[start]!=";":
 
      # print("error when parsing Node")
 
      return (start,None)
 
    i=skipWhitespace(str,start+1)
 
    i,x=Property.create(str,i)
 
    while x is not None:
 
      if x.name in res.properties:
 
        print('error: duplicate "{0}" property in node at position {1}. second value ignored'.format(x.name,start))
 
      else:
 
        res.properties[x.name]=x
 
      i=skipWhitespace(str,i)
 
      i,x=Property.create(str,i)
 
    return (i,res)
 
    
 
  def setProperty(self,name,value):
 
    self.properties[name]=value
 
    # zkontrolovat typ value
 
    
 
  def getProperty(self,name):
 
    if name in self.properties: return self.properties[name]
 
    else: return None
 
  
 
	properties=dict()
 
	
 
	def create(str,start):
 
		res=Node()
 
		if str[start]!=";":
 
			# print("error when parsing Node")
 
			return (start,None)
 
		i=skipWhitespace(str,start+1)
 
		i,x=Property.create(str,i)
 
		while x is not None:
 
			if x.name in res.properties:
 
				print('error: duplicate "{0}" property in node at position {1}. second value ignored'.format(x.name,start))
 
			else:
 
				res.properties[x.name]=x
 
			i=skipWhitespace(str,i)
 
			i,x=Property.create(str,i)
 
		return (i,res)
 
		
 
	def setProperty(self,name,value):
 
		self.properties[name]=value
 
		# zkontrolovat typ value
 
		
 
	def getProperty(self,name):
 
		if name in self.properties: return self.properties[name]
 
		else: return None
 
	
 
class Property:
 
  name=""
 
  value=""
 
  
 
  def create(str,start):
 
    res=Property()
 
    i,x=Property.ident(str,start)
 
    if x is None:
 
      return (start,None)
 
    res.name=x
 
    i,x=PropValue.create(str,i,res.name)
 
    if x is None:
 
      print('error when parsing property "{0}" at position {1}'.format(res.name,i))
 
      return (start,None)
 
    # while x is not None: # přesunuto do PropValue.listOf
 
      # res.values.append(x)
 
      # i=skipWhitespace(str,i)
 
      # i,x=PropValue.create(str,i,res.name)
 
    res.values.append(x) # !! podezřelé
 
    return (i,res)
 
    
 
  def ident(str,start):
 
    r=re.compile(r"[A-Z]+")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    return (m.end(),m.group())
 
	name=""
 
	value=""
 
	
 
	def create(str,start):
 
		res=Property()
 
		i,x=Property.ident(str,start)
 
		if x is None:
 
			return (start,None)
 
		res.name=x
 
		i,x=PropValue.create(str,i,res.name)
 
		if x is None:
 
			print('error when parsing property "{0}" at position {1}'.format(res.name,i))
 
			return (start,None)
 
		# while x is not None: # přesunuto do PropValue.listOf
 
			# res.values.append(x)
 
			# i=skipWhitespace(str,i)
 
			# i,x=PropValue.create(str,i,res.name)
 
		res.values.append(x) # !! podezřelé
 
		return (i,res)
 
		
 
	def ident(str,start):
 
		r=re.compile(r"[A-Z]+")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		return (m.end(),m.group())
 
 
class PropValue:
 
  type=""
 
  value=None
 
  patterns=dict()
 
  
 
  def create(str,start,name):
 
    if name in PropValue.patterns:
 
      return PropValue.patterns[name](str,start)
 
    else:
 
      print('warning, unknown property "{0}" at position {1}'.format(name,start))
 
      return PropValue.singleton(PropValue.anything)(str,start)
 
  
 
  # def singleton(str,start,vType):
 
    # if str[start]!="[":
 
      # return (start,None)
 
    # i,x=vType(str,start+1)
 
    # if x is None: return (start,None)
 
    # if str[i]!="]":
 
      # return (start,None)
 
    # return (i+1,x)
 
  
 
  def choose(*vTypes):
 
    def f(str,start):
 
      for vType in vTypes:
 
        i,x=vType(str,start)
 
        if x is not None: return (i,x)
 
      return (start,None)
 
    return f
 
  
 
  def singleton(vType):
 
    def f(str,start):
 
      if str[start]!="[":
 
        return (start,None)
 
      i,x=vType(str,start+1)
 
      if x is None: return (start,None)
 
      if str[i]!="]":
 
        return (start,None)
 
      return (i+1,x)
 
    return f
 
    
 
  # def listOf(str,start,vType,allowEmpty=False):
 
    # res=[]
 
    # i,x=singleton(str,start,vType)
 
    # # singleton(vType) if vType not tuple else compose(vType[0],vType[1])
 
    # while x!=None:
 
      # res.append(x)
 
      # i,x=singleton(str,i,vType)
 
    # if len(res)==0 and not allowEmpty: return (start,None)
 
    # return (i,res)
 
    
 
  def listOf(vType,allowEmpty=False):
 
    def f(str,start):
 
      res=[]
 
      single=singleton(vType)
 
      i,x=single(str,start)
 
      while x!=None:
 
        res.append(x)
 
        i,x=single(str,i)
 
      if len(res)==0 and not allowEmpty: return (start,None)
 
      return (i,res)
 
    return f
 
    
 
  # def compose(str,start,vTypeA,vTypeB):
 
    # i,a=vTypeA(str,start)
 
    # if a==None or str[i]!=":": return (start,None)
 
    # i,b=vTypeB(str,i+1)
 
    # if b==None: return start,None
 
    # return (i,(a,b))
 
    
 
  def compose(vTypeA,vTypeB):
 
    def f(str,start):
 
      i,a=vTypeA(str,start)
 
      # print(">",i,a)
 
      if a==None or str[i]!=":": return (start,None)
 
      i,b=vTypeB(str,i+1)
 
      # print(">",i,b)
 
      if b==None: return start,None
 
      return (i,(a,b))
 
    return f
 
  
 
  def number(str,start):
 
    r=re.compile(r"(\+|-|)\d+")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    res=int(m.group(0))
 
    return (m.end(),res)
 
    
 
  def real(str,start):
 
    r=re.compile(r"(\+|-|)\d+(\.\d+)?")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    res=float(m.group(0))
 
    return (m.end(),res)
 
    
 
  def double(str,start):
 
    r=re.compile(r"1|2")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    res=int(m.group(0))
 
    return (m.end(),res)
 
  
 
  def color(str,start):
 
    r=re.compile(r"B|W")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    return (m.end(),m.group(0))
 
    
 
  # def simpleText(str,start):
 
    # res=""
 
    # esc=False
 
    # lineBreak=False
 
    # for c in str:
 
      # if esc:
 
        # res+=c
 
        # esc=False
 
      # elif c=="\\":
 
        # esc=True
 
      # elif c=="]":
 
        # break
 
      # else:
 
        # res+=c
 
    # return res
 
  
 
  def text(simple=True,composed=False):
 
    def f(str,start):
 
      res=""
 
      esc=False
 
      lastC=""
 
      for i,c in enumerate(str[start:],start):
 
        if esc:
 
          if c!="\n" and c!="\r": res+=c
 
          esc=False
 
        elif (c=="\n" and lastC=="\r") or (c=="\r" and lastC=="\n"): pass
 
        elif c=="\r" or c=="\n" and not simple:
 
          res+="\n"
 
        elif c.isspace():
 
          res+=" "
 
        elif c=="\\":
 
          esc=True
 
        elif c=="]" or (c==":" and composed):
 
          break
 
        else:
 
          res+=c
 
        lastC=c
 
      return (i,res)
 
    return f
 
    
 
  def empty(str,start): return (start,"")
 
  
 
  def anything(str,start): # přidat listOf
 
    esc=False
 
    for i,c in enumerate(str[start:],start):
 
      if esc: esc=False
 
      elif c=="\\": esc=True
 
      elif c=="]": break
 
    return (i,str[start:i])
 
  
 
  # go specific
 
  def point(str,start):
 
    r=re.compile(r"[a-zA-Z]{2}|") # !! limit to board size
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    if m.group(0)=="": # pass, !! tt
 
      return (m.end(),tuple())
 
    col=m.group(0)[0]
 
    row=m.group(0)[1]
 
    col=ord(col) - (ord("a") if "a"<=col<="z" else ord("A")-26)
 
    row=ord(row) - (ord("a") if "a"<=row<="z" else ord("A")-26)
 
    return (m.end(),(col,row))
 
	type=""
 
	value=None
 
	patterns=dict()
 
	
 
	def create(str,start,name):
 
		if name in PropValue.patterns:
 
			return PropValue.patterns[name](str,start)
 
		else:
 
			print('warning, unknown property "{0}" at position {1}'.format(name,start))
 
			return PropValue.singleton(PropValue.anything)(str,start)
 
	
 
	# def singleton(str,start,vType):
 
		# if str[start]!="[":
 
			# return (start,None)
 
		# i,x=vType(str,start+1)
 
		# if x is None: return (start,None)
 
		# if str[i]!="]":
 
			# return (start,None)
 
		# return (i+1,x)
 
	
 
	def choose(*vTypes):
 
		def f(str,start):
 
			for vType in vTypes:
 
				i,x=vType(str,start)
 
				if x is not None: return (i,x)
 
			return (start,None)
 
		return f
 
	
 
	def singleton(vType):
 
		def f(str,start):
 
			if str[start]!="[":
 
				return (start,None)
 
			i,x=vType(str,start+1)
 
			if x is None: return (start,None)
 
			if str[i]!="]":
 
				return (start,None)
 
			return (i+1,x)
 
		return f
 
		
 
	# def listOf(str,start,vType,allowEmpty=False):
 
		# res=[]
 
		# i,x=singleton(str,start,vType)
 
		# # singleton(vType) if vType not tuple else compose(vType[0],vType[1])
 
		# while x!=None:
 
			# res.append(x)
 
			# i,x=singleton(str,i,vType)
 
		# if len(res)==0 and not allowEmpty: return (start,None)
 
		# return (i,res)
 
		
 
	def listOf(vType,allowEmpty=False):
 
		def f(str,start):
 
			res=[]
 
			single=singleton(vType)
 
			i,x=single(str,start)
 
			while x!=None:
 
				res.append(x)
 
				i,x=single(str,i)
 
			if len(res)==0 and not allowEmpty: return (start,None)
 
			return (i,res)
 
		return f
 
		
 
	# def compose(str,start,vTypeA,vTypeB):
 
		# i,a=vTypeA(str,start)
 
		# if a==None or str[i]!=":": return (start,None)
 
		# i,b=vTypeB(str,i+1)
 
		# if b==None: return start,None
 
		# return (i,(a,b))
 
		
 
	def compose(vTypeA,vTypeB):
 
		def f(str,start):
 
			i,a=vTypeA(str,start)
 
			# print(">",i,a)
 
			if a==None or str[i]!=":": return (start,None)
 
			i,b=vTypeB(str,i+1)
 
			# print(">",i,b)
 
			if b==None: return start,None
 
			return (i,(a,b))
 
		return f
 
	
 
	def number(str,start):
 
		r=re.compile(r"(\+|-|)\d+")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		res=int(m.group(0))
 
		return (m.end(),res)
 
		
 
	def real(str,start):
 
		r=re.compile(r"(\+|-|)\d+(\.\d+)?")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		res=float(m.group(0))
 
		return (m.end(),res)
 
		
 
	def double(str,start):
 
		r=re.compile(r"1|2")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		res=int(m.group(0))
 
		return (m.end(),res)
 
	
 
	def color(str,start):
 
		r=re.compile(r"B|W")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		return (m.end(),m.group(0))
 
		
 
	# def simpleText(str,start):
 
		# res=""
 
		# esc=False
 
		# lineBreak=False
 
		# for c in str:
 
			# if esc:
 
				# res+=c
 
				# esc=False
 
			# elif c=="\\":
 
				# esc=True
 
			# elif c=="]":
 
				# break
 
			# else:
 
				# res+=c
 
		# return res
 
	
 
	def text(simple=True,composed=False):
 
		def f(str,start):
 
			res=""
 
			esc=False
 
			lastC=""
 
			for i,c in enumerate(str[start:],start):
 
				if esc:
 
					if c!="\n" and c!="\r": res+=c
 
					esc=False
 
				elif (c=="\n" and lastC=="\r") or (c=="\r" and lastC=="\n"): pass
 
				elif c=="\r" or c=="\n" and not simple:
 
					res+="\n"
 
				elif c.isspace():
 
					res+=" "
 
				elif c=="\\":
 
					esc=True
 
				elif c=="]" or (c==":" and composed):
 
					break
 
				else:
 
					res+=c
 
				lastC=c
 
			return (i,res)
 
		return f
 
		
 
	def empty(str,start): return (start,"")
 
	
 
	def anything(str,start): # přidat listOf
 
		esc=False
 
		for i,c in enumerate(str[start:],start):
 
			if esc: esc=False
 
			elif c=="\\": esc=True
 
			elif c=="]": break
 
		return (i,str[start:i])
 
	
 
	# go specific
 
	def point(str,start):
 
		r=re.compile(r"[a-zA-Z]{2}|") # !! limit to board size
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		if m.group(0)=="": # pass, !! tt
 
			return (m.end(),tuple())
 
		col=m.group(0)[0]
 
		row=m.group(0)[1]
 
		col=ord(col) - (ord("a") if "a"<=col<="z" else ord("A")-26)
 
		row=ord(row) - (ord("a") if "a"<=row<="z" else ord("A")-26)
 
		return (m.end(),(col,row))
 
 
  move=point
 
  stone=point
 
  
 
  patterns={
 
    "B":singleton(move),
 
    "KO":singleton(empty),
 
    "MN":singleton(number),
 
    "W":singleton(move),
 
    "AB":listOf(stone), #
 
    "AE":listOf(point), #
 
    "AW":listOf(stone), #
 
    "PL":singleton(color),
 
    "C":singleton(text(simple=False)),
 
    "DM":singleton(double),
 
    "GB":singleton(double),
 
    "GW":singleton(double),
 
    "HO":singleton(double),
 
    "N":singleton(text()),
 
    "UC":singleton(double),
 
    "V":singleton(real),
 
    "BM":singleton(double),
 
    "DO":singleton(empty),
 
    "IT":singleton(empty),
 
    "TE":singleton(double),
 
    "AR":listOf(compose(point,point)), #
 
    "CR":listOf(point), #
 
    "DD":listOf(point,allowEmpty=True), #
 
    "LB":listOf(compose(point,text())), #
 
    "LN":listOf(compose(point,point)), #
 
    "MA":listOf(point), #
 
    "SL":listOf(point), #
 
    "SQ":listOf(point), #
 
    "TR":listOf(point), #
 
    "AP":singleton(compose(text(composed=True),text())), #
 
    "CA":singleton(text()),
 
    "FF":singleton(number),
 
    "GM":singleton(number),
 
    "ST":singleton(number),
 
    "SZ":choose(singleton(number),singleton(compose(number,number))), #
 
    "AN":singleton(text()),
 
    "BR":singleton(text()),
 
    "BT":singleton(text()),
 
    "CP":singleton(text()),
 
    "DT":singleton(text()),
 
    "EV":singleton(text()),
 
    "GN":singleton(text()),
 
    "GC":singleton(text(simple=False)),
 
    "ON":singleton(text()),
 
    "OT":singleton(text()),
 
    "PB":singleton(text()),
 
    "PC":singleton(text()),
 
    "PW":singleton(text()),
 
    "RE":singleton(text()),
 
    "RO":singleton(text()),
 
    "RU":singleton(text()),
 
    "SO":singleton(text()),
 
    "TM":singleton(real),
 
    "US":singleton(text()),
 
    "WR":singleton(text()),
 
    "WT":singleton(text()),
 
    "BL":singleton(real),
 
    "OB":singleton(number),
 
    "OW":singleton(number),
 
    "WL":singleton(real),
 
    "FG":choose(singleton(empty),singleton(compose(number,text()))), #
 
    "PM":singleton(number),
 
    "VW":listOf(point,allowEmpty=True), #
 
    
 
    # go specific
 
    "HA":singleton(number),
 
    "KM":singleton(real),
 
    "TB":listOf(point,allowEmpty=True),
 
    "TW":listOf(point,allowEmpty=True)
 
  }
 
	move=point
 
	stone=point
 
	
 
	patterns={
 
		"B":singleton(move),
 
		"KO":singleton(empty),
 
		"MN":singleton(number),
 
		"W":singleton(move),
 
		"AB":listOf(stone), #
 
		"AE":listOf(point), #
 
		"AW":listOf(stone), #
 
		"PL":singleton(color),
 
		"C":singleton(text(simple=False)),
 
		"DM":singleton(double),
 
		"GB":singleton(double),
 
		"GW":singleton(double),
 
		"HO":singleton(double),
 
		"N":singleton(text()),
 
		"UC":singleton(double),
 
		"V":singleton(real),
 
		"BM":singleton(double),
 
		"DO":singleton(empty),
 
		"IT":singleton(empty),
 
		"TE":singleton(double),
 
		"AR":listOf(compose(point,point)), #
 
		"CR":listOf(point), #
 
		"DD":listOf(point,allowEmpty=True), #
 
		"LB":listOf(compose(point,text())), #
 
		"LN":listOf(compose(point,point)), #
 
		"MA":listOf(point), #
 
		"SL":listOf(point), #
 
		"SQ":listOf(point), #
 
		"TR":listOf(point), #
 
		"AP":singleton(compose(text(composed=True),text())), #
 
		"CA":singleton(text()),
 
		"FF":singleton(number),
 
		"GM":singleton(number),
 
		"ST":singleton(number),
 
		"SZ":choose(singleton(number),singleton(compose(number,number))), #
 
		"AN":singleton(text()),
 
		"BR":singleton(text()),
 
		"BT":singleton(text()),
 
		"CP":singleton(text()),
 
		"DT":singleton(text()),
 
		"EV":singleton(text()),
 
		"GN":singleton(text()),
 
		"GC":singleton(text(simple=False)),
 
		"ON":singleton(text()),
 
		"OT":singleton(text()),
 
		"PB":singleton(text()),
 
		"PC":singleton(text()),
 
		"PW":singleton(text()),
 
		"RE":singleton(text()),
 
		"RO":singleton(text()),
 
		"RU":singleton(text()),
 
		"SO":singleton(text()),
 
		"TM":singleton(real),
 
		"US":singleton(text()),
 
		"WR":singleton(text()),
 
		"WT":singleton(text()),
 
		"BL":singleton(real),
 
		"OB":singleton(number),
 
		"OW":singleton(number),
 
		"WL":singleton(real),
 
		"FG":choose(singleton(empty),singleton(compose(number,text()))), #
 
		"PM":singleton(number),
 
		"VW":listOf(point,allowEmpty=True), #
 
		
 
		# go specific
 
		"HA":singleton(number),
 
		"KM":singleton(real),
 
		"TB":listOf(point,allowEmpty=True),
 
		"TW":listOf(point,allowEmpty=True)
 
	}
 
 
"""def property(str):
 
  # i=propIdent(str)
 
  # if i<0: return -1
 
  # j=i
 
  # i=propValue(str[i:])
 
  # while i>=0:
 
    # j+=i
 
    # i=propValue(str[i:])
 
  # return j
 
	# i=propIdent(str)
 
	# if i<0: return -1
 
	# j=i
 
	# i=propValue(str[i:])
 
	# while i>=0:
 
		# j+=i
 
		# i=propValue(str[i:])
 
	# return j
 
 
def propIdent(str):
 
  m=re.match(r"[A-Z]+",str)
 
  if m is None: return -1
 
  return m.end()
 
	m=re.match(r"[A-Z]+",str)
 
	if m is None: return -1
 
	return m.end()
 
 
def propValue(str):
 
  i=cValueType(str[1:])
 
  if str[0]=="[" and i>=0 and str[i]=="]": return i+1
 
  else: return -1
 
	i=cValueType(str[1:])
 
	if str[0]=="[" and i>=0 and str[i]=="]": return i+1
 
	else: return -1
 
 
class propValue:
 
  pass
 
	pass
 
 
def cValueType(str,start):
 
  matches=[real,number,double,color,simpleText]
 
  for f in matches:
 
    i,x=f(str,start)
 
    if x is not None: return i,x
 
  return 1/0
 
	matches=[real,number,double,color,simpleText]
 
	for f in matches:
 
		i,x=f(str,start)
 
		if x is not None: return i,x
 
	return 1/0
 
 
def number(str,start):
 
  r=re.compile(r"(\+|-|)\d+")
 
  m=r.match(str,start)
 
  if m is None: return (-1,None)
 
  x=int(m.group(0))
 
  return (m.end(),x)
 
	r=re.compile(r"(\+|-|)\d+")
 
	m=r.match(str,start)
 
	if m is None: return (-1,None)
 
	x=int(m.group(0))
 
	return (m.end(),x)
 
 
def real(str):
 
  m=re.match(r"(\+|-|)\d+(\.\d+)?",str)
 
  if m is None: return -1
 
  return m.end()
 
	m=re.match(r"(\+|-|)\d+(\.\d+)?",str)
 
	if m is None: return -1
 
	return m.end()
 
 
def double(str):
 
  m=re.match(r"1|2",str)
 
  if m is None: return -1
 
  return m.end()
 
  
 
	m=re.match(r"1|2",str)
 
	if m is None: return -1
 
	return m.end()
 
	
 
def color(str):
 
  m=re.match(r"B|W",str)
 
  if m is None: return -1
 
  return m.end()
 
  
 
	m=re.match(r"B|W",str)
 
	if m is None: return -1
 
	return m.end()
 
	
 
def simpleText(str):
 
  res=r""
 
  esc=False
 
  for c in str:
 
    if esc:
 
      res+=c
 
      esc=False
 
    elif c=="\\":
 
      esc=True
 
    elif c=="]":
 
      break
 
    else:
 
      res+=c
 
  return res"""
 
	res=r""
 
	esc=False
 
	for c in str:
 
		if esc:
 
			res+=c
 
			esc=False
 
		elif c=="\\":
 
			esc=True
 
		elif c=="]":
 
			break
 
		else:
 
			res+=c
 
	return res"""
 
 
sgf=open("in/1-Hora-Simara.sgf").read()
 
sgfParser.py
Show inline comments
 
import re
 
  
 
	
 
def skipWhitespace(str,start):
 
  i=start
 
  while i<len(str) and str[i].isspace(): i+=1
 
  return i
 
	i=start
 
	while i<len(str) and str[i].isspace(): i+=1
 
	return i
 
 
class Collection:
 
  gameTrees=[]
 
  
 
  def __init__(self,str):
 
    self.gameTrees=[]
 
    i,x=GameTree.create(str,0)
 
    if x is None:
 
      print("error when parsing Collection")
 
      return
 
    while x is not None:
 
      self.gameTrees.append(x)
 
      i,x=GameTree.create(str,i)
 
  
 
	gameTrees=[]
 
	
 
	def __init__(self,str):
 
		self.gameTrees=[]
 
		i,x=GameTree.create(str,0)
 
		if x is None:
 
			print("error when parsing Collection")
 
			return
 
		while x is not None:
 
			self.gameTrees.append(x)
 
			i,x=GameTree.create(str,i)
 
	
 
class GameTree:
 
  nodes=[]
 
  branches=[]
 
  
 
  # def __init__(self,str,start):
 
    # self.nodes=[]
 
    # self.branches=[]
 
    # if str[start]!="(":
 
      # print("error when parsing GameTree")
 
      # return (-1,None)
 
    # i,x=Node(str,start+1)
 
    # if x is None:
 
      # print("error when parsing GameTree")
 
      # return (-1,None)
 
    # while x is not None:
 
      # self.nodes.append(x)
 
      # i,x=Node(str,i)
 
    # if str[i]!=")":
 
      # print("error when parsing GameTree")
 
      # return (-1,None)
 
    # return (i+1,self)
 
    
 
  def create(str,start):
 
    res=GameTree()
 
    i=skipWhitespace(str,start)
 
    if i>=len(str) or str[i]!="(":
 
      # print("error when parsing GameTree")
 
      return (start,None)
 
    i,x=Node.create(str,start+1)
 
    if x is None:
 
      # print("error when parsing GameTree")
 
      return (i,None)
 
    while x is not None:
 
      res.nodes.append(x)
 
      i=skipWhitespace(str,i)
 
      i,x=Node.create(str,i)
 
    i=skipWhitespace(str,i)
 
    i,x=GameTree.create(str,i)
 
    while x is not None:
 
      res.branches.append(x)
 
      i=skipWhitespace(str,i)
 
      i,x=GameTree.create(str,i)
 
    if str[i]!=")":
 
      # print("error when parsing GameTree")
 
      return (i,None)
 
    return (i+1,res)
 
  
 
	nodes=[]
 
	branches=[]
 
	
 
	# def __init__(self,str,start):
 
		# self.nodes=[]
 
		# self.branches=[]
 
		# if str[start]!="(":
 
			# print("error when parsing GameTree")
 
			# return (-1,None)
 
		# i,x=Node(str,start+1)
 
		# if x is None:
 
			# print("error when parsing GameTree")
 
			# return (-1,None)
 
		# while x is not None:
 
			# self.nodes.append(x)
 
			# i,x=Node(str,i)
 
		# if str[i]!=")":
 
			# print("error when parsing GameTree")
 
			# return (-1,None)
 
		# return (i+1,self)
 
		
 
	def create(str,start):
 
		res=GameTree()
 
		i=skipWhitespace(str,start)
 
		if i>=len(str) or str[i]!="(":
 
			# print("error when parsing GameTree")
 
			return (start,None)
 
		i,x=Node.create(str,start+1)
 
		if x is None:
 
			# print("error when parsing GameTree")
 
			return (i,None)
 
		while x is not None:
 
			res.nodes.append(x)
 
			i=skipWhitespace(str,i)
 
			i,x=Node.create(str,i)
 
		i=skipWhitespace(str,i)
 
		i,x=GameTree.create(str,i)
 
		while x is not None:
 
			res.branches.append(x)
 
			i=skipWhitespace(str,i)
 
			i,x=GameTree.create(str,i)
 
		if str[i]!=")":
 
			# print("error when parsing GameTree")
 
			return (i,None)
 
		return (i+1,res)
 
	
 
class Node:
 
  properties=dict()
 
  
 
  def create(str,start):
 
    res=Node()
 
    if str[start]!=";":
 
      # print("error when parsing Node")
 
      return (start,None)
 
    i=skipWhitespace(str,start+1)
 
    i,x=Property.create(str,start+1)
 
    while x is not None:
 
      if x.name in res.properties:
 
        print('error: duplicate "{0}" property in node at position {1}. second value ignored'.format(x.name,start))
 
      else:
 
        res.properties[x.name]=x
 
      i=skipWhitespace(str,i)
 
      i,x=Property.create(str,i)
 
    return (i,res)
 
    
 
  def setProperty(self,name,value):
 
    self.properties[name]=value
 
    # zkontrolovat typ value
 
    
 
  def getProperty(self,name):
 
    if name in self.properties: return self.properties[name]
 
    else: return None
 
  
 
	properties=dict()
 
	
 
	def create(str,start):
 
		res=Node()
 
		if str[start]!=";":
 
			# print("error when parsing Node")
 
			return (start,None)
 
		i=skipWhitespace(str,start+1)
 
		i,x=Property.create(str,start+1)
 
		while x is not None:
 
			if x.name in res.properties:
 
				print('error: duplicate "{0}" property in node at position {1}. second value ignored'.format(x.name,start))
 
			else:
 
				res.properties[x.name]=x
 
			i=skipWhitespace(str,i)
 
			i,x=Property.create(str,i)
 
		return (i,res)
 
		
 
	def setProperty(self,name,value):
 
		self.properties[name]=value
 
		# zkontrolovat typ value
 
		
 
	def getProperty(self,name):
 
		if name in self.properties: return self.properties[name]
 
		else: return None
 
	
 
class Property:
 
  name=""
 
  value=""
 
  
 
  def create(str,start):
 
    res=Property()
 
    i,x=Property.ident(str,start)
 
    if x is None:
 
      return (start,None)
 
    res.name=x
 
    i,x=PropValue.create(str,i,res.name)
 
    if x is None:
 
      print('error when parsing property "{0}" at position {1}'.format(res.name,i))
 
      return (start,None)
 
    # while x is not None: # přesunuto do PropValue.listOf
 
      # res.values.append(x)
 
      # i=skipWhitespace(str,i)
 
      # i,x=PropValue.create(str,i,res.name)
 
    return (i,res)
 
    
 
  def ident(str,start):
 
    r=re.compile(r"[A-Z]+")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    return (m.end(),m.group())
 
	name=""
 
	value=""
 
	
 
	def create(str,start):
 
		res=Property()
 
		i,x=Property.ident(str,start)
 
		if x is None:
 
			return (start,None)
 
		res.name=x
 
		i,x=PropValue.create(str,i,res.name)
 
		if x is None:
 
			print('error when parsing property "{0}" at position {1}'.format(res.name,i))
 
			return (start,None)
 
		# while x is not None: # přesunuto do PropValue.listOf
 
			# res.values.append(x)
 
			# i=skipWhitespace(str,i)
 
			# i,x=PropValue.create(str,i,res.name)
 
		return (i,res)
 
		
 
	def ident(str,start):
 
		r=re.compile(r"[A-Z]+")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		return (m.end(),m.group())
 
 
class PropValue:
 
  type=""
 
  value=None
 
  patterns=dict()
 
  
 
  def create(str,start,name):
 
    if name in PropValue.patterns:
 
      return PropValue.patterns[name](str,start)
 
    else:
 
      print('warning, unknown property "{0}" at position {1}'.format(name,start))
 
      return PropValue.singleton(PropValue.anything)(str,start)
 
  
 
  # def singleton(str,start,vType):
 
    # if str[start]!="[":
 
      # return (start,None)
 
    # i,x=vType(str,start+1)
 
    # if x is None: return (start,None)
 
    # if str[i]!="]":
 
      # return (start,None)
 
    # return (i+1,x)
 
  
 
  def choose(*vTypes):
 
    def f(str,start):
 
      for vType in vTypes:
 
        i,x=vType(str,start)
 
        if x is not None: return (i,x)
 
      return (start,None)
 
    return f
 
  
 
  def singleton(vType):
 
    def f(str,start):
 
      if str[start]!="[":
 
        return (start,None)
 
      i,x=vType(str,start+1)
 
      if x is None: return (start,None)
 
      if str[i]!="]":
 
        return (start,None)
 
      return (i+1,x)
 
    return f
 
    
 
  # def listOf(str,start,vType,allowEmpty=False):
 
    # res=[]
 
    # i,x=singleton(str,start,vType)
 
    # # singleton(vType) if vType not tuple else compose(vType[0],vType[1])
 
    # while x!=None:
 
      # res.append(x)
 
      # i,x=singleton(str,i,vType)
 
    # if len(res)==0 and not allowEmpty: return (start,None)
 
    # return (i,res)
 
    
 
  def listOf(vType,allowEmpty=False):
 
    def f(str,start):
 
      res=[]
 
      single=singleton(vType)
 
      i,x=single(str,start)
 
      while x!=None:
 
        res.append(x)
 
        i,x=single(str,i)
 
      if len(res)==0 and not allowEmpty: return (start,None)
 
      return (i,res)
 
    return f
 
    
 
  # def compose(str,start,vTypeA,vTypeB):
 
    # i,a=vTypeA(str,start)
 
    # if a==None or str[i]!=":": return (start,None)
 
    # i,b=vTypeB(str,i+1)
 
    # if b==None: return start,None
 
    # return (i,(a,b))
 
    
 
  def compose(vTypeA,vTypeB):
 
    def f(str,start):
 
      i,a=vTypeA(str,start)
 
      # print(">",i,a)
 
      if a==None or str[i]!=":": return (start,None)
 
      i,b=vTypeB(str,i+1)
 
      # print(">",i,b)
 
      if b==None: return start,None
 
      return (i,(a,b))
 
    return f
 
  
 
  def number(str,start):
 
    r=re.compile(r"(\+|-|)\d+")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    res=int(m.group(0))
 
    return (m.end(),res)
 
    
 
  def real(str,start):
 
    r=re.compile(r"(\+|-|)\d+(\.\d+)?")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    res=float(m.group(0))
 
    return (m.end(),res)
 
    
 
  def double(str,start):
 
    r=re.compile(r"1|2")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    res=int(m.group(0))
 
    return (m.end(),res)
 
  
 
  def color(str,start):
 
    r=re.compile(r"B|W")
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    return (m.end(),m.group(0))
 
    
 
  # def simpleText(str,start):
 
    # res=""
 
    # esc=False
 
    # lineBreak=False
 
    # for c in str:
 
      # if esc:
 
        # res+=c
 
        # esc=False
 
      # elif c=="\\":
 
        # esc=True
 
      # elif c=="]":
 
        # break
 
      # else:
 
        # res+=c
 
    # return res
 
  
 
  def text(simple=True,composed=False):
 
    def f(str,start):
 
      res=""
 
      esc=False
 
      lastC=""
 
      for i,c in enumerate(str[start:],start):
 
        if esc:
 
          if c!="\n" and c!="\r": res+=c
 
          esc=False
 
        elif (c=="\n" and lastC=="\r") or (c=="\r" and lastC=="\n"): pass
 
        elif c=="\r" or c=="\n" and not simple:
 
          res+="\n"
 
        elif c.isspace():
 
          res+=" "
 
        elif c=="\\":
 
          esc=True
 
        elif c=="]" or (c==":" and composed):
 
          break
 
        else:
 
          res+=c
 
        lastC=c
 
      return (i,res)
 
    return f
 
    
 
  def empty(str,start): return (start,"")
 
  
 
  def anything(str,start):
 
    esc=False
 
    for i,c in enumerate(str[start:],start):
 
      if esc: esc=False
 
      elif c=="\\": esc=True
 
      elif c=="]": break
 
    return (i,str[start:i])
 
  
 
  # go specific
 
  def point(str,start):
 
    r=re.compile(r"[a-zA-Z]{2}|") # !! limit to board size
 
    m=r.match(str,start)
 
    if m is None: return (start,None)
 
    if m.group(0)=="": # pass, !! tt
 
      return (m.end(),tuple())
 
    col=m.group(0)[0]
 
    row=m.group(0)[1]
 
    col=ord(col) - (ord("a") if "a"<=col<="z" else ord("A")-26)
 
    row=ord(row) - (ord("a") if "a"<=row<="z" else ord("A")-26)
 
    return (m.end(),(col,row))
 
	type=""
 
	value=None
 
	patterns=dict()
 
	
 
	def create(str,start,name):
 
		if name in PropValue.patterns:
 
			return PropValue.patterns[name](str,start)
 
		else:
 
			print('warning, unknown property "{0}" at position {1}'.format(name,start))
 
			return PropValue.singleton(PropValue.anything)(str,start)
 
	
 
	# def singleton(str,start,vType):
 
		# if str[start]!="[":
 
			# return (start,None)
 
		# i,x=vType(str,start+1)
 
		# if x is None: return (start,None)
 
		# if str[i]!="]":
 
			# return (start,None)
 
		# return (i+1,x)
 
	
 
	def choose(*vTypes):
 
		def f(str,start):
 
			for vType in vTypes:
 
				i,x=vType(str,start)
 
				if x is not None: return (i,x)
 
			return (start,None)
 
		return f
 
	
 
	def singleton(vType):
 
		def f(str,start):
 
			if str[start]!="[":
 
				return (start,None)
 
			i,x=vType(str,start+1)
 
			if x is None: return (start,None)
 
			if str[i]!="]":
 
				return (start,None)
 
			return (i+1,x)
 
		return f
 
		
 
	# def listOf(str,start,vType,allowEmpty=False):
 
		# res=[]
 
		# i,x=singleton(str,start,vType)
 
		# # singleton(vType) if vType not tuple else compose(vType[0],vType[1])
 
		# while x!=None:
 
			# res.append(x)
 
			# i,x=singleton(str,i,vType)
 
		# if len(res)==0 and not allowEmpty: return (start,None)
 
		# return (i,res)
 
		
 
	def listOf(vType,allowEmpty=False):
 
		def f(str,start):
 
			res=[]
 
			single=singleton(vType)
 
			i,x=single(str,start)
 
			while x!=None:
 
				res.append(x)
 
				i,x=single(str,i)
 
			if len(res)==0 and not allowEmpty: return (start,None)
 
			return (i,res)
 
		return f
 
		
 
	# def compose(str,start,vTypeA,vTypeB):
 
		# i,a=vTypeA(str,start)
 
		# if a==None or str[i]!=":": return (start,None)
 
		# i,b=vTypeB(str,i+1)
 
		# if b==None: return start,None
 
		# return (i,(a,b))
 
		
 
	def compose(vTypeA,vTypeB):
 
		def f(str,start):
 
			i,a=vTypeA(str,start)
 
			# print(">",i,a)
 
			if a==None or str[i]!=":": return (start,None)
 
			i,b=vTypeB(str,i+1)
 
			# print(">",i,b)
 
			if b==None: return start,None
 
			return (i,(a,b))
 
		return f
 
	
 
	def number(str,start):
 
		r=re.compile(r"(\+|-|)\d+")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		res=int(m.group(0))
 
		return (m.end(),res)
 
		
 
	def real(str,start):
 
		r=re.compile(r"(\+|-|)\d+(\.\d+)?")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		res=float(m.group(0))
 
		return (m.end(),res)
 
		
 
	def double(str,start):
 
		r=re.compile(r"1|2")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		res=int(m.group(0))
 
		return (m.end(),res)
 
	
 
	def color(str,start):
 
		r=re.compile(r"B|W")
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		return (m.end(),m.group(0))
 
		
 
	# def simpleText(str,start):
 
		# res=""
 
		# esc=False
 
		# lineBreak=False
 
		# for c in str:
 
			# if esc:
 
				# res+=c
 
				# esc=False
 
			# elif c=="\\":
 
				# esc=True
 
			# elif c=="]":
 
				# break
 
			# else:
 
				# res+=c
 
		# return res
 
	
 
	def text(simple=True,composed=False):
 
		def f(str,start):
 
			res=""
 
			esc=False
 
			lastC=""
 
			for i,c in enumerate(str[start:],start):
 
				if esc:
 
					if c!="\n" and c!="\r": res+=c
 
					esc=False
 
				elif (c=="\n" and lastC=="\r") or (c=="\r" and lastC=="\n"): pass
 
				elif c=="\r" or c=="\n" and not simple:
 
					res+="\n"
 
				elif c.isspace():
 
					res+=" "
 
				elif c=="\\":
 
					esc=True
 
				elif c=="]" or (c==":" and composed):
 
					break
 
				else:
 
					res+=c
 
				lastC=c
 
			return (i,res)
 
		return f
 
		
 
	def empty(str,start): return (start,"")
 
	
 
	def anything(str,start):
 
		esc=False
 
		for i,c in enumerate(str[start:],start):
 
			if esc: esc=False
 
			elif c=="\\": esc=True
 
			elif c=="]": break
 
		return (i,str[start:i])
 
	
 
	# go specific
 
	def point(str,start):
 
		r=re.compile(r"[a-zA-Z]{2}|") # !! limit to board size
 
		m=r.match(str,start)
 
		if m is None: return (start,None)
 
		if m.group(0)=="": # pass, !! tt
 
			return (m.end(),tuple())
 
		col=m.group(0)[0]
 
		row=m.group(0)[1]
 
		col=ord(col) - (ord("a") if "a"<=col<="z" else ord("A")-26)
 
		row=ord(row) - (ord("a") if "a"<=row<="z" else ord("A")-26)
 
		return (m.end(),(col,row))
 
 
  move=point
 
  stone=point
 
  
 
  patterns={
 
    "B":singleton(move),
 
    "KO":singleton(empty),
 
    "MN":singleton(number),
 
    "W":singleton(move),
 
    "AB":listOf(stone), #
 
    "AE":listOf(point), #
 
    "AW":listOf(stone), #
 
    "PL":singleton(color),
 
    "C":singleton(text(simple=False)),
 
    "DM":singleton(double),
 
    "GB":singleton(double),
 
    "GW":singleton(double),
 
    "HO":singleton(double),
 
    "N":singleton(text()),
 
    "UC":singleton(double),
 
    "V":singleton(real),
 
    "BM":singleton(double),
 
    "DO":singleton(empty),
 
    "IT":singleton(empty),
 
    "TE":singleton(double),
 
    "AR":listOf(compose(point,point)), #
 
    "CR":listOf(point), #
 
    "DD":listOf(point,allowEmpty=True), #
 
    "LB":listOf(compose(point,text())), #
 
    "LN":listOf(compose(point,point)), #
 
    "MA":listOf(point), #
 
    "SL":listOf(point), #
 
    "SQ":listOf(point), #
 
    "TR":listOf(point), #
 
    "AP":singleton(compose(text(composed=True),text())), #
 
    "CA":singleton(text()),
 
    "FF":singleton(number),
 
    "GM":singleton(number),
 
    "ST":singleton(number),
 
    "SZ":choose(singleton(number),singleton(compose(number,number))), #
 
    "AN":singleton(text()),
 
    "BR":singleton(text()),
 
    "BT":singleton(text()),
 
    "CP":singleton(text()),
 
    "DT":singleton(text()),
 
    "EV":singleton(text()),
 
    "GN":singleton(text()),
 
    "GC":singleton(text(simple=False)),
 
    "ON":singleton(text()),
 
    "OT":singleton(text()),
 
    "PB":singleton(text()),
 
    "PC":singleton(text()),
 
    "PW":singleton(text()),
 
    "RE":singleton(text()),
 
    "RO":singleton(text()),
 
    "RU":singleton(text()),
 
    "SO":singleton(text()),
 
    "TM":singleton(real),
 
    "US":singleton(text()),
 
    "WR":singleton(text()),
 
    "WT":singleton(text()),
 
    "BL":singleton(real),
 
    "OB":singleton(number),
 
    "OW":singleton(number),
 
    "WL":singleton(real),
 
    "FG":choose(singleton(empty),singleton(compose(number,text()))), #
 
    "PM":singleton(number),
 
    "VW":listOf(point,allowEmpty=True), #
 
    
 
    # go specific
 
    "HA":singleton(number),
 
    "KM":singleton(real),
 
    "TB":listOf(point,allowEmpty=True),
 
    "TW":listOf(point,allowEmpty=True)
 
  }
 
	move=point
 
	stone=point
 
	
 
	patterns={
 
		"B":singleton(move),
 
		"KO":singleton(empty),
 
		"MN":singleton(number),
 
		"W":singleton(move),
 
		"AB":listOf(stone), #
 
		"AE":listOf(point), #
 
		"AW":listOf(stone), #
 
		"PL":singleton(color),
 
		"C":singleton(text(simple=False)),
 
		"DM":singleton(double),
 
		"GB":singleton(double),
 
		"GW":singleton(double),
 
		"HO":singleton(double),
 
		"N":singleton(text()),
 
		"UC":singleton(double),
 
		"V":singleton(real),
 
		"BM":singleton(double),
 
		"DO":singleton(empty),
 
		"IT":singleton(empty),
 
		"TE":singleton(double),
 
		"AR":listOf(compose(point,point)), #
 
		"CR":listOf(point), #
 
		"DD":listOf(point,allowEmpty=True), #
 
		"LB":listOf(compose(point,text())), #
 
		"LN":listOf(compose(point,point)), #
 
		"MA":listOf(point), #
 
		"SL":listOf(point), #
 
		"SQ":listOf(point), #
 
		"TR":listOf(point), #
 
		"AP":singleton(compose(text(composed=True),text())), #
 
		"CA":singleton(text()),
 
		"FF":singleton(number),
 
		"GM":singleton(number),
 
		"ST":singleton(number),
 
		"SZ":choose(singleton(number),singleton(compose(number,number))), #
 
		"AN":singleton(text()),
 
		"BR":singleton(text()),
 
		"BT":singleton(text()),
 
		"CP":singleton(text()),
 
		"DT":singleton(text()),
 
		"EV":singleton(text()),
 
		"GN":singleton(text()),
 
		"GC":singleton(text(simple=False)),
 
		"ON":singleton(text()),
 
		"OT":singleton(text()),
 
		"PB":singleton(text()),
 
		"PC":singleton(text()),
 
		"PW":singleton(text()),
 
		"RE":singleton(text()),
 
		"RO":singleton(text()),
 
		"RU":singleton(text()),
 
		"SO":singleton(text()),
 
		"TM":singleton(real),
 
		"US":singleton(text()),
 
		"WR":singleton(text()),
 
		"WT":singleton(text()),
 
		"BL":singleton(real),
 
		"OB":singleton(number),
 
		"OW":singleton(number),
 
		"WL":singleton(real),
 
		"FG":choose(singleton(empty),singleton(compose(number,text()))), #
 
		"PM":singleton(number),
 
		"VW":listOf(point,allowEmpty=True), #
 
		
 
		# go specific
 
		"HA":singleton(number),
 
		"KM":singleton(real),
 
		"TB":listOf(point,allowEmpty=True),
 
		"TW":listOf(point,allowEmpty=True)
 
	}
 
 
"""def property(str):
 
  # i=propIdent(str)
 
  # if i<0: return -1
 
  # j=i
 
  # i=propValue(str[i:])
 
  # while i>=0:
 
    # j+=i
 
    # i=propValue(str[i:])
 
  # return j
 
	# i=propIdent(str)
 
	# if i<0: return -1
 
	# j=i
 
	# i=propValue(str[i:])
 
	# while i>=0:
 
		# j+=i
 
		# i=propValue(str[i:])
 
	# return j
 
 
def propIdent(str):
 
  m=re.match(r"[A-Z]+",str)
 
  if m is None: return -1
 
  return m.end()
 
	m=re.match(r"[A-Z]+",str)
 
	if m is None: return -1
 
	return m.end()
 
 
def propValue(str):
 
  i=cValueType(str[1:])
 
  if str[0]=="[" and i>=0 and str[i]=="]": return i+1
 
  else: return -1
 
	i=cValueType(str[1:])
 
	if str[0]=="[" and i>=0 and str[i]=="]": return i+1
 
	else: return -1
 
 
class propValue:
 
  pass
 
	pass
 
 
def cValueType(str,start):
 
  matches=[real,number,double,color,simpleText]
 
  for f in matches:
 
    i,x=f(str,start)
 
    if x is not None: return i,x
 
  return 1/0
 
	matches=[real,number,double,color,simpleText]
 
	for f in matches:
 
		i,x=f(str,start)
 
		if x is not None: return i,x
 
	return 1/0
 
 
def number(str,start):
 
  r=re.compile(r"(\+|-|)\d+")
 
  m=r.match(str,start)
 
  if m is None: return (-1,None)
 
  x=int(m.group(0))
 
  return (m.end(),x)
 
	r=re.compile(r"(\+|-|)\d+")
 
	m=r.match(str,start)
 
	if m is None: return (-1,None)
 
	x=int(m.group(0))
 
	return (m.end(),x)
 
 
def real(str):
 
  m=re.match(r"(\+|-|)\d+(\.\d+)?",str)
 
  if m is None: return -1
 
  return m.end()
 
	m=re.match(r"(\+|-|)\d+(\.\d+)?",str)
 
	if m is None: return -1
 
	return m.end()
 
 
def double(str):
 
  m=re.match(r"1|2",str)
 
  if m is None: return -1
 
  return m.end()
 
  
 
	m=re.match(r"1|2",str)
 
	if m is None: return -1
 
	return m.end()
 
	
 
def color(str):
 
  m=re.match(r"B|W",str)
 
  if m is None: return -1
 
  return m.end()
 
  
 
	m=re.match(r"B|W",str)
 
	if m is None: return -1
 
	return m.end()
 
	
 
def simpleText(str):
 
  res=r""
 
  esc=False
 
  for c in str:
 
    if esc:
 
      res+=c
 
      esc=False
 
    elif c=="\\":
 
      esc=True
 
    elif c=="]":
 
      break
 
    else:
 
      res+=c
 
  return res"""
 
	res=r""
 
	esc=False
 
	for c in str:
 
		if esc:
 
			res+=c
 
			esc=False
 
		elif c=="\\":
 
			esc=True
 
		elif c=="]":
 
			break
 
		else:
 
			res+=c
 
	return res"""
 
 
sgf=open("in/1-Hora-Simara.sgf").read()
 
0 comments (0 inline, 0 general)