Files @ 2ed7f0dab5ef
Branch filter:

Location: Diana/src/sgfParser/property.py - annotation

Laman
expanding compressed game trees
b66f5379b832
b66f5379b832
b66f5379b832
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
2ed7f0dab5ef
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
b66f5379b832
b66f5379b832
2ed7f0dab5ef
b66f5379b832
2ed7f0dab5ef
2ed7f0dab5ef
b66f5379b832
b66f5379b832
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
b66f5379b832
b66f5379b832
cfcff53c74e6
b66f5379b832
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
2ed7f0dab5ef
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
cfcff53c74e6
2ed7f0dab5ef
import re


GAME_INFO=1
UNKNOWN=99


def choose(*vTypes):
	def f(s,start):
		for vType in vTypes:
			i,x=vType(s,start)
			if x is not None: return (i,x)
		return (start,None)
	return f


def singleton(vType):
	def f(s,start):
		if s[start]!="[":
			return (start,None)
		i,x=vType(s,start+1)
		if x is None: return (start,None)
		if s[i]!="]":
			return (start,None)
		return (i+1,x)
	return f


def listOf(vType,allowEmpty=False):
	def f(s,start):
		res=[]
		single=singleton(vType)
		i,x=single(s,start)
		while x!=None:
			res.append(x)
			i,x=single(s,i)
		if len(res)==0 and not allowEmpty: return (start,None)
		return (i,res)
	return f


def compose(vTypeA,vTypeB):
	def f(s,start):
		i,a=vTypeA(s,start)
		if a==None or s[i]!=":": return (start,None)
		i,b=vTypeB(s,i+1)
		if b==None: return start,None
		return (i,(a,b))
	return f


def number(s,start):
	r=re.compile(r"(\+|-|)\d+")
	m=r.match(s,start)
	if m is None: return (start,None)
	res=int(m.group(0))
	return (m.end(),res)


def real(s,start):
	r=re.compile(r"(\+|-|)\d+(\.\d+)?")
	m=r.match(s,start)
	if m is None: return (start,None)
	res=float(m.group(0))
	return (m.end(),res)


def double(s,start):
	r=re.compile(r"1|2")
	m=r.match(s,start)
	if m is None: return (start,None)
	res=int(m.group(0))
	return (m.end(),res)


def color(s,start):
	r=re.compile(r"B|W")
	m=r.match(s,start)
	if m is None: return (start,None)
	return (m.end(),m.group(0))


def text(simple=True,composed=False):
	def f(s,start):
		res=""
		esc=False
		lastC=""
		for i,c in enumerate(s[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(s,start): return (start,"")


def anything(s,start):
	esc=False
	for i,c in enumerate(s[start:],start):
		if esc: esc=False
		elif c=="\\": esc=True
		elif c=="]": break
	return (i,s[start:i])


# go specific
def point(s,start):
	r=re.compile(r"[a-zA-Z]{2}|") # !! limit to board size
	m=r.match(s,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


class Property:
	def __init__(self):
		self.name=""
		self.value=""

	@staticmethod
	def create(s,start):
		res=Property()
		i,x=Property.ident(s,start)
		if x is None:
			return (start,None)
		res.name=x
		i,x=Property.createValue(s,i,res.name)
		if x is None:
			print('error when parsing property "{0}" at position {1}'.format(res.name,i))
			return (start,None)
		res.value=x
		return (i,res)

	@staticmethod
	def ident(s,start):
		r=re.compile(r"[A-Z]+")
		m=r.match(s,start)
		if m is None: return (start,None)
		return (m.end(),m.group())

	@staticmethod
	def createValue(s,start,name):
		if name in Property.patterns:
			return Property.patterns[name](s,start)
		else:
			print('warning, unknown property "{0}" at position {1}'.format(name,start))
			return singleton(anything)(s,start)

	@property
	def type(self):
		gameInfo={"AN","BR","BT","CP","DT","EV","GN","GC","ON","OT","PB","PC","PW","RE","RO","RU","SO","TM","US","WR","WT"}
		if self.name in gameInfo: return GAME_INFO
		else: return UNKNOWN

	def copy(self):
		res=Property()
		res.name=self.name
		# !! wouldn't work for listOf(listOf())
		res.value=self.value if not isinstance(self.value,list) else self.value[:]
		return res

	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)
	}


# !! TODO: date