Changeset - 36b0271e7393
[Not reviewed]
default
0 2 0
Laman - 6 years ago 2019-05-29 16:30:43

more lenient and robust error handling
2 files changed with 9 insertions and 3 deletions:
0 comments (0 inline, 0 general)
src/diana/sgfParser/node.py
Show inline comments
 
from collections import deque
 
import logging as log
 

	
 
from . import skipWhitespace, ParserWarning
 
from .property import Property, GAME_INFO
 

	
 

	
 
class Node:
 
	def __init__(self):
 
		self.properties=dict()
 
		self.parent=None
 
		self.children=[]
 

	
 
	@staticmethod
 
	def fits(s,i):
 
		return i<len(s) and s[i]==";"
 

	
 
	@staticmethod
 
	def create(s,start):
 
		assert Node.fits(s,start)
 
		res=Node()
 

	
 
		i=skipWhitespace(s,start+1)
 
		while Property.fits(s,i):
 
			i,x=Property.create(s,i)
 
			if x.name in res.properties:
 
				# !! raise or log or ignore
 
				raise ParserWarning('duplicate "{0}" property in a node. second value ignored'.format(x.name),s,i)
 
				log.warning(ParserWarning('duplicate "{0}" property in a node. second value ignored'.format(x.name),s,i))
 
			else:
 
				res.properties[x.name]=x
 
			i=skipWhitespace(s,i)
 
		return (i,res)
 

	
 
	def listGINodes(self):
 
		if self.isGINode(): yield self
 
		empty=not self.isGINode()
 

	
 
		node=self
 
		while node.parent:
 
			node=node.parent
src/diana/sgfParser/property.py
Show inline comments
 
import re
 
import logging as log
 

	
 
from .propValues import choose, singleton, listOf, compose, number, real, double, color, text, empty, anything, point, move, stone
 
from . import skipWhitespace, ParserError
 

	
 
GAME_INFO=1
 
UNKNOWN=99
 

	
 

	
 
class Property:
 
	identRegexp=re.compile(r"[A-Z]+")
 

	
 
	def __init__(self):
 
@@ -15,25 +16,30 @@ class Property:
 
		self.value=""
 

	
 
	@staticmethod
 
	def fits(s,i):
 
		return i<len(s) and s[i].isupper()
 

	
 
	@staticmethod
 
	def create(s,start):
 
		assert Property.fits(s,start)
 
		res=Property()
 
		i,res.name=Property.ident(s,start)
 
		i=skipWhitespace(s,i)
 
		i,x=Property.createValue(s,i,res.name)
 
		try:
 
			i,x=Property.createValue(s,i,res.name)
 
		except ParserError as e: # malformed value
 
			log.warning(e)
 
			i,x=choose(listOf(anything), singleton(anything))(s,i)
 
			res.name="_"+res.name
 
		res.value=x
 
		i=skipWhitespace(s,i)
 
		return (i,res)
 

	
 
	@staticmethod
 
	def ident(s,start):
 
		m=Property.identRegexp.match(s,start)
 
		if m is None: raise ParserError("expected a property identifier matching '[A-Z]+'",s,start)
 
		return (m.end(),m.group())
 

	
 
	@staticmethod
 
	def createValue(s,start,name):
0 comments (0 inline, 0 general)