diff --git a/diana.py b/diana.py --- a/diana.py +++ b/diana.py @@ -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=''' + padding=15 + gridSize=28 + highNumbers=True + + def __init__(self): + self.content=''' - - - - \n'''.format(2*self.padding+18*self.gridSize) - self.footer="\n" + + + + \n'''.format(2*self.padding+18*self.gridSize) + self.footer="\n" - grid=' \n' + grid=' \n' - # okraje desky - for i in (0,18): - self.content+=' \n'.format(self.padding, 18*self.gridSize+self.padding, self.gridSize*i+self.padding, self.gridSize*i+self.padding) - self.content+=' \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+=' \n'.format(self.padding, 18*self.gridSize+self.padding, self.gridSize*i+self.padding, self.gridSize*i+self.padding) + self.content+=' \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+=' \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+=' \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+=' \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+=' \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+=' {4}\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+=' {4}\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)) diff --git a/go.py b/go.py --- a/go.py +++ b/go.py @@ -1,33 +1,33 @@ 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 diff --git a/sgf-compresor.py b/sgf-compresor.py deleted file mode 100755 --- a/sgf-compresor.py +++ /dev/null @@ -1,124 +0,0 @@ -import re -import sys - -def compressValues(s): - vals=[] - indicesX=[] - for m in re.finditer(r"\[.*?[^\\]\]",s,flags=re.DOTALL): - vals.append(m.group(0)[1:-1]) - indicesX.append(m.span()) - i=len(indicesX)-1 - for start,end in reversed(indicesX): - s=s[:start+1]+"$"+str(i)+s[end-1:] - i-=1 - return s,vals - -s=open("c:/Users/Laman/Documents/go/EuroGoTV1-x.sgf",encoding="utf8").read() -s,d=compressValues(s) - -print(s) -print(d[:20]) - -sys.exit(0) - -# # # - -# http://en.wikipedia.org/wiki/Recursive_descent_parser - -# # # - -import collections -import re - -Token = collections.namedtuple('Token', ['typ', 'value']) - -def tokenize(s): - keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'} - token_specification = [ - ('PROPID',r'[A-Z]+'), - ('PROPVAL',r'\[\$\d+\]'), - ('NODE',r';'), - ('LPARENTHESIS',r'\('), - ('RPARENTHESIS',r'\)'), - ('SKIP',r'\s') - ] - tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification) - get_token = re.compile(tok_regex).match - line = 1 - pos = line_start = 0 - mo = get_token(s) - while mo is not None: - typ = mo.lastgroup - if typ == 'NEWLINE': - line_start = pos - line += 1 - elif typ != 'SKIP': - val = mo.group(typ) - if typ == 'ID' and val in keywords: - typ = val - yield Token(typ, val, line, mo.start()-line_start) - pos = mo.end() - mo = get_token(s, pos) - if pos != len(s): - raise RuntimeError('Unexpected character %r on line %d' %(s[pos], line)) - -statements = ''' - IF quantity THEN - total := total + price * quantity; - tax := price * 0.05; - ENDIF; -''' - -for token in tokenize(statements): - print(token) - -tokens=["list of tokens"] -i=0 -sym - -def getSym(): - sym=token[i] - i+=1 - -def accept(s): - if sym==s: - getSym() - return True - else: - return False - -def expect(s): - if accept(s): - return True - else: - pass # error - return False - -def propValue(): - if accept(lbracket) and cValueType() and expect(rbracket): - pass - else: - pass # error - -def propIdent(): - accept(ident) - -def propertyX(): - propIdent() - while propValue(): pass - -def node(): - accept(semicolon) - propertyX() - -def sequence(): - while node(): pass - -def gameTree(): - accept(lparenthesis) - sequence() - while gameTree(): pass - expect(rparenthesis) - -def collection(): - while gameTree(): pass \ No newline at end of file diff --git a/sgf.py b/sgf.py --- a/sgf.py +++ b/sgf.py @@ -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) 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() diff --git a/sgfParser.py b/sgfParser.py --- a/sgfParser.py +++ b/sgfParser.py @@ -1,434 +1,434 @@ import re - + def skipWhitespace(str,start): - i=start - while 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()