Files @ cfcff53c74e6
Branch filter:

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

Laman
little property refactoring
b66f5379b832
b66f5379b832
b66f5379b832
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
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
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
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
cfcff53c74e6
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
b66f5379b832
cfcff53c74e6
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
b66f5379b832
cfcff53c74e6
b66f5379b832
b66f5379b832
import re


GAME_INFO=1
UNKNOWN=99


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=PropValue.create(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())

	@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 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 PropValue:
	def __init__(self):
		self.type=""
		self.value=None

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

	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