Code Search for Developers
 
 
  

parser.py from Thousand Parsec at Krugle


Show parser.py syntax highlighted


import pprint
from types import *
import xml.parsers.expat

# Squash warnings about hex/oct
import warnings

# Local Imports
import Structures
import objects

convert = {
	'id':	int,
}

class Parser(object):
	def __init__(self):
		self.mode = []
		self.attrs = []
		self.structures = []

	def StartElementHandler(self, name, attrs):
		#print "Start", name, attrs
		self.mode.append(name)
		self.attrs.append(attrs)
		
		if name in ("packet",):
			# Figure out what this packet is based on
			if attrs.has_key("base"):
				base = eval("objects." + attrs['base'])
			else:
				base = objects.Packet

			class NewPacket(base):
				pass
			self.packet = NewPacket

		if name in ("structure",):
			self.structures.append([])

	def EndElementHandler(self, name):
		#print "End", name
		if name != self.mode[-1]:
			raise ValueError("Element matching error")
		name = self.mode.pop(-1)
		attrs = self.attrs.pop(-1)

		# Useless for us properties
		if name in ("notes", "note", "example"):
			return

		#print name, self.mode
		#print attrs, self.attrs
		#print "----------------------------------"
		# Packet Attributes
		if name in ("direction",):
			if self.mode[-1] != "packet":
				raise ValueError("Got a %s when not in a packet!" % name)
				
			self.attrs[-1][name] = self.data
			del self.data
		
		# Finished a packet
		if name in ("packet",):
			for key, value in attrs.items():
				if key in convert:
					value = convert[key](value)
				setattr(self.packet, key, value)

			print self.packet.name
		
			if not hasattr(objects, self.packet.name):
				setattr(objects, self.packet.name, self.packet)
			else:
				# Better check the prebuilt one is identical
				print "Ignoring packet of type %s because it is hand coded."
			del self.packet
			print

		# Finished a structure
		if name in ("structure",):
			if self.mode[-1] == "packet":
				structures = self.structures.pop(-1)
				self.packet.structures = structures

				for structure in structures:
					# FIXME: This doesn't seem the correct place to put this....
					def StructurePropertySet(self, value, name=structure.name):
						structure.check(value)
						setattr(self, "__%s" % name, value)
	
					def StructurePropertyGet(self, name=structure.name):
						return getattr(self, "__%s" % name)
	
					setattr(self.packet, name, property(StructurePropertyGet, StructurePropertySet, structure.description))
					return
			
			if self.mode[-1] == "list":
				self.attrs[-1]['structures'] = self.structures.pop(-1)
				return
		
		# Structure components
		types = ("string", "character", "integer", "list", "group", "enumeration", "datetime",)
		if name in types:
			if self.mode[-1] != "structure":
				raise ValueError("Got a %s when not in a structure!" % name)
			
			nattrs = {}
			for key, value in attrs.items():
				if key in ("size",):
					value = long(value)
				nattrs[str(key)] = value

			# Check that atleast the basic arugments exist
			packetname = self.attrs[self.__packetLevel()]['name']
			if not nattrs.has_key('name'):
				raise SyntaxError("%s on %s does not have a name" % (name.title(), packetname))
			if not nattrs.has_key('longname'):
				warnings.warn("%s on %s does not have a longname" % (nattrs['name'], packetname), SyntaxWarning)
			if not nattrs.has_key('description'):
				warnings.warn("%s on %s does not have a description" % (nattrs['name'], packetname), SyntaxWarning)

			print "Structures.%sStructure" % name.title(), nattrs
			self.structures[-1].append(eval("Structures.%sStructure" % name.title())(**nattrs))
		
		# Properties of a packet or structure
		if name in ("name", "longname", "description", "example",):
			if self.mode[-1] == "packet":
				if name == "description":
					name = "__doc__"
				setattr(self.packet, name, self.data)

			if self.mode[-2] == "structure":
				if not self.mode[-1] in types:
					raise ValueError("Got a %s when not in a structure component!" % name)
				self.attrs[-1][name] = self.data
			del self.data

	def __packetLevel(self):
		n = -1
		while self.mode[n] != "packet":
			n -= 1
		return n

	def CharacterDataHandler(self, data):
		self.data = data

	def CreateParser(cls):
		p = xml.parsers.expat.ParserCreate()
		c = cls()

		#print "dict", type(c), c.__dict__, cls.__dict__
		for name in cls.__dict__.keys():
			if name.startswith('_') or name == "CreateParser":
				continue
			
			value = getattr(c, name)
			if callable(value):
				setattr(p, name, value)

		return p
	CreateParser = classmethod(CreateParser)

if __name__ == "__main__":
	parser = Parser.CreateParser()
	parser.ParseFile(file("protocol.xml", "r"))

	print objects
	print dir(objects)

	print objects.Okay(2, "Test")




See more files for this project here

Thousand Parsec

Thousand Parsec is a framework for turn based 4 X\'s game (eXplore, eXpand, eXploit, eXterminate). Designed for long games, supporting massive universes and has an easily expanded tech tree.

Project homepage: http://sourceforge.net/projects/thousandparsec
Programming language(s): C++,Python
License: other

  objects/
    Header.py
    Packet.py
    __init__.py
  .boring
  Structures.py
  libtpproto2-py.tailor
  parser.py
  protocol.dtd
  protocol.xml
  xstruct.py