diff options
Diffstat (limited to 'sgfparser.py')
-rw-r--r-- | sgfparser.py | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/sgfparser.py b/sgfparser.py new file mode 100644 index 0000000..6b52522 --- /dev/null +++ b/sgfparser.py @@ -0,0 +1,100 @@ +# Begin -- grammar generated by Yapps +import sys, re +from yapps import runtime + +class SGFScanner(runtime.Scanner): + patterns = [ + ("''", re.compile('')), + ('"\\\\]"', re.compile('\\]')), + ('"\\\\["', re.compile('\\[')), + ('";"', re.compile(';')), + ('"\\\\)"', re.compile('\\)')), + ('"\\\\("', re.compile('\\(')), + ('\\s+', re.compile('\\s+')), + ('Point', re.compile('[a-zA-Z]{2}')), + ('Move', re.compile('[a-zA-Z]{2}')), + ('Stone', re.compile('[a-zA-Z]{2}')), + ('PropID', re.compile('([a-z]*[A-Z]){1,2}[a-z]*')), + ('Number', re.compile('[+-]?[0-9]+')), + ('Real', re.compile('[+-]?[0-9]+(\\.[0-9]+)?')), + ('Color', re.compile('(B|W)')), + ('Text', re.compile('[^\\]]*')), + ] + def __init__(self, str,*args,**kw): + runtime.Scanner.__init__(self,None,{'\\s+':None,},str,*args,**kw) + +class SGF(runtime.Parser): + Context = runtime.Context + def GameTree(self, _parent=None): + _context = self.Context(_parent, self._scanner, 'GameTree', []) + self._scan('"\\\\("', context=_context) + res = [] + while 1: + Node = self.Node(_context) + res.append(Node) + if self._peek('";"', '"\\\\)"', '"\\\\("', context=_context) != '";"': break + while self._peek('"\\\\)"', '"\\\\("', context=_context) == '"\\\\("': + GameTree = self.GameTree(_context) + res.append(GameTree) + self._scan('"\\\\)"', context=_context) + return res + + def Node(self, _parent=None): + _context = self.Context(_parent, self._scanner, 'Node', []) + self._scan('";"', context=_context) + res = [] + while 1: + Property = self.Property(_context) + res.append(Property) + if self._peek('PropID', '";"', '"\\\\)"', '"\\\\("', context=_context) != 'PropID': break + return dict(res) + + def Property(self, _parent=None): + _context = self.Context(_parent, self._scanner, 'Property', []) + PropID = self._scan('PropID', context=_context) + res = (PropID, []) + while 1: + self._scan('"\\\\["', context=_context) + ValueType = self.ValueType(_context) + self._scan('"\\\\]"', context=_context) + res[1].append(ValueType) + if self._peek('"\\\\["', 'PropID', '";"', '"\\\\)"', '"\\\\("', context=_context) != '"\\\\["': break + return res + + def ValueType(self, _parent=None): + _context = self.Context(_parent, self._scanner, 'ValueType', []) + _token = self._peek('Number', 'Real', 'Color', 'Move', 'Text', "''", context=_context) + if _token == 'Number': + Number = self._scan('Number', context=_context) + return int(Number) + elif _token == 'Real': + Real = self._scan('Real', context=_context) + return float(Real) + elif _token == 'Color': + Color = self._scan('Color', context=_context) + return Color + elif _token == 'Move': + Move = self._scan('Move', context=_context) + return (Move[0].islower() and ord(Move[0])-96 or ord(Move[0])-64, Move[1].islower() and ord(Move[1])-96 or ord(Move[1])-64) + elif _token == 'Text': + Text = self._scan('Text', context=_context) + return Text + else: # == "''" + self._scan("''", context=_context) + return None + + +def parse(rule, text): + P = SGF(SGFScanner(text)) + return runtime.wrap_error_reporter(P, rule) + +if __name__ == '__main__': + from sys import argv, stdin + if len(argv) >= 2: + if len(argv) >= 3: + f = open(argv[2],'r') + else: + f = stdin + print parse(argv[1], f.read()) + else: print >>sys.stderr, 'Args: <rule> [<filename>]' +# End -- grammar generated by Yapps |