diff --git a/src/diana/sgfParser/propValues.py b/src/diana/sgfParser/propValues.py --- a/src/diana/sgfParser/propValues.py +++ b/src/diana/sgfParser/propValues.py @@ -4,175 +4,180 @@ from . import ParserError, skipWhitespac class Regexp: - number=re.compile(r"(\+|-|)\d+") - real=re.compile(r"(\+|-|)\d+(\.\d+)?") - point=re.compile(r"[a-zA-Z]{2}|") - text=re.compile(r"(?:.*?[^\\])??(?:\\\\)*(?=])", re.DOTALL) - composedText=re.compile(r"(?:.*?[^\\])??(?:\\\\)*(?=]|:)", re.DOTALL) + number = re.compile(r"(\+|-|)\d+") + real = re.compile(r"(\+|-|)\d+(\.\d+)?") + point = re.compile(r"[a-zA-Z]{2}|") + text = re.compile(r"(?:.*?[^\\])??(?:\\\\)*(?=])", re.DOTALL) + composedText = re.compile(r"(?:.*?[^\\])??(?:\\\\)*(?=]|:)", re.DOTALL) class Text: - softBreaks=re.compile(r"(^|[^\\])((\\\\)*)\\((\n\r)|(\r\n)|\r|\n)") - whitespace=re.compile(r"[\t\f\v]") - simpleWhitespace=re.compile(r"[\t\f\v\n\r]") - removeSlashes=re.compile(r"(^|[^\\])((\\\\)*)\\($|[^\\])") - unescapeSlashes=re.compile(r"\\\\") + softBreaks = re.compile(r"(^|[^\\])((\\\\)*)\\((\n\r)|(\r\n)|\r|\n)") + whitespace = re.compile(r"[\t\f\v]") + simpleWhitespace = re.compile(r"[\t\f\v\n\r]") + removeSlashes = re.compile(r"(^|[^\\])((\\\\)*)\\($|[^\\])") + unescapeSlashes = re.compile(r"\\\\") class Composed: - def __init__(self,a=None,b=None): - self.a=a - self.b=b + def __init__(self, a=None, b=None): + self.a = a + self.b = b def __str__(self): - return "{0}:{1}".format(self.a,self.b) + return "{0}:{1}".format(self.a, self.b) class Point: - def __init__(self,c,r): - self.r=r - self.c=c + def __init__(self, c, r): + self.r = r + self.c = c def __iter__(self): yield self.c yield self.r def __str__(self): - a=ord("a") - return chr(a+self.c)+chr(a+self.r) + a = ord("a") + return chr(a+self.c) + chr(a+self.r) ## Metatype matching one of the provided types. # # Returns the first match, so the order is important. def choose(*vTypes): - def f(s,start): + def f(s, start): for vType in vTypes: try: - i,x=vType(s,start) - return (i,x) - except ParserError: pass - raise ParserError("no variant of a 'choose' property value matched",s,start) + (i, x) = vType(s, start) + return (i, x) + except ParserError: + pass + raise ParserError("no variant of a 'choose' property value matched", s, start) return f -def singletonFits(s,i): - return i=len(s) or s[i]!=":": - raise ParserError("expected a composed property value separated by ':'",s,i) - i,b=vTypeB(s,i+1) - return (i,Composed(a,b)) +def compose(vTypeA, vTypeB): + def f(s, start): + (i, a) = vTypeA(s, start) + if i >= len(s) or s[i] != ":": + raise ParserError("expected a composed property value separated by ':'", s, i) + (i, b) = vTypeB(s, i+1) + return (i, Composed(a, b)) return f -def number(s,start): - m=Regexp.number.match(s,start) - if m is None: raise ParserError("expected a number matching '{0}'".format(Regexp.number.pattern),s,start) - res=int(m.group(0)) - return (m.end(),res) +def number(s, start): + m = Regexp.number.match(s, start) + if m is None: + raise ParserError("expected a number matching '{0}'".format(Regexp.number.pattern), s, start) + res = int(m.group(0)) + return (m.end(), res) -def real(s,start): - m=Regexp.real.match(s,start) - if m is None: raise ParserError("expected a real number matching '{0}'".format(Regexp.real.pattern),s,start) - res=float(m.group(0)) - return (m.end(),res) +def real(s, start): + m = Regexp.real.match(s, start) + if m is None: + raise ParserError("expected a real number matching '{0}'".format(Regexp.real.pattern), s, start) + res = float(m.group(0)) + return (m.end(), res) -def double(s,start): - c=s[start] +def double(s, start): + c = s[start] if c not in ("1", "2"): - raise ParserError("expected a double value, either '1' or '2'",s,start) - return (start+1,c) + raise ParserError("expected a double value, either '1' or '2'", s, start) + return (start+1, c) def color(s,start): - c=s[start] + c = s[start] if c not in ("B", "W"): - raise ParserError("expected a color value, either 'B' or 'W'",s,start) - return (start+1,c) + raise ParserError("expected a color value, either 'B' or 'W'", s, start) + return (start+1, c) -def text(simple=True,composed=False): - def f(s,start): - regexps=Regexp.Text - m=Regexp.composedText.match(s,start) if composed else Regexp.text.match(s,start) - res=m.group(0) - res=regexps.softBreaks.sub(r"\1\2",res) # remove soft line breaks +def text(simple=True, composed=False): + def f(s, start): + regexps = Regexp.Text + m = Regexp.composedText.match(s, start) if composed else Regexp.text.match(s, start) + res = m.group(0) + res = regexps.softBreaks.sub(r"\1\2", res) # remove soft line breaks if simple: - res=regexps.simpleWhitespace.sub(" ",res) # convert whitespace to spaces, no escapes + res = regexps.simpleWhitespace.sub(" ", res) # convert whitespace to spaces, no escapes else: - res=regexps.whitespace.sub(" ",res) # convert whitespace to spaces, no escapes - res=regexps.removeSlashes.sub(r"\1\2\4",res) - res=regexps.unescapeSlashes.sub(r"\\",res) # unescape slashes + res = regexps.whitespace.sub(" ", res) # convert whitespace to spaces, no escapes + res = regexps.removeSlashes.sub(r"\1\2\4", res) + res = regexps.unescapeSlashes.sub(r"\\", res) # unescape slashes - return (m.end(),res) + return (m.end(), res) return f -def empty(s,start): return (start,"") +def empty(s, start): + return (start, "") -def anything(s,start): - esc=False - i=start - for i,c in enumerate(s[start:],start): - if esc: esc=False - elif c=="\\": esc=True - elif c=="]": break - return (i,s[start:i]) +def anything(s, start): + esc = False + i = start + 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): - m=Regexp.point.match(s,start) # !! limit to board size - if m is None: raise ParserError("expected a point value matching '{0}'".format(Regexp.point.pattern),s,start) - 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(),Point(col,row)) +def point(s, start): + m = Regexp.point.match(s, start) # !! limit to board size + if m is None: + raise ParserError("expected a point value matching '{0}'".format(Regexp.point.pattern), s, start) + 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(), Point(col, row)) -move=point -stone=point +move = point +stone = point