X-Git-Url: https://git.yukkurigames.com/?p=python-bulletml.git;a=blobdiff_plain;f=bulletml%2Fparser.py;h=62f00d4ca1720bab29669316810775f220151855;hp=b39437ac8dd951d3c20def3b6523c2b68f12f1ed;hb=41f351faf847cb5bc88c7ff5fc6c21bafc9aa5ee;hpb=dd06ecce6efd9815f6ff09f2a985738dd699288d diff --git a/bulletml/parser.py b/bulletml/parser.py index b39437a..62f00d4 100644 --- a/bulletml/parser.py +++ b/bulletml/parser.py @@ -1,6 +1,10 @@ """BulletML parser. -http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html +This is based on the format described at +http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/bulletml_ref_e.html. + +Unless you are adding support for new tags, the only class you should +care about in here is BulletML. """ from __future__ import division @@ -31,7 +35,7 @@ def realtag(element): class ParamList(object): """List of parameter definitions.""" - def __init__(self, params=[]): + def __init__(self, params=()): self.params = list(params) @classmethod @@ -312,7 +316,13 @@ class BulletRef(object): type(self).__name__, self.params, self.bullet) class ActionDef(object): - """Action definition.""" + """Action definition. + + To support parsing new actions, add tags to + ActionDef.CONSTRUCTORS. It maps tag names to classes with a + FromElement classmethod, which take the BulletML instance and + ElementTree element as arguments. + """ # This is self-referential, so it's filled in later. CONSTRUCTORS = dict() @@ -435,6 +445,12 @@ class BulletML(object): A BulletML document is a collection of bullets, actions, and firings, as well as a base game type. + + You can add tags to the BulletML.CONSTRUCTORS dictionary to extend + its parsing. It maps tag names to classes with a FromElement + classmethod, which take the BulletML instance and ElementTree + element as arguments. + """ CONSTRUCTORS = dict( @@ -443,22 +459,26 @@ class BulletML(object): fire=FireDef, ) - def __init__(self, source): - self.bullets = {} - self.actions = {} - self.fires = {} - - self._bullet_refs = [] - self._action_refs = [] - self._fire_refs = [] + def __init__(self, type="none", bullets=None, fires=None, actions=None): + self.type = type + self.bullets = {} if bullets is None else bullets + self.actions = {} if actions is None else actions + self.fires = {} if fires is None else fires + @classmethod + def FromDocument(cls, source): + """Return a BulletML instance based on a string or file-like.""" if isinstance(source, (str, unicode)): source = StringIO(source) tree = ElementTree() root = tree.parse(source) - self.type = root.get("type", "none") + self = cls(type=root.get("type", "none")) + + self._bullet_refs = [] + self._action_refs = [] + self._fire_refs = [] for element in root.getchildren(): tag = realtag(element) @@ -483,6 +503,8 @@ class BulletML(object): self.actions.pop(None, None) self.fires.pop(None, None) + return self + @property def top(self): """Get a list of all top-level actions."""