def ruleTest(self,rule,series): for s in series: #print "s: %s" % s parser = MakeParser(rule) self.stateTest(parser, s[0], '') for i, t in enumerate(s[1:]): #print "sending token: %s,%s" % (i, t) disp = parser.parse(t['tok']) self.stateTest(parser, t, disp)
class ActionParser(Parser): def __init__(self,rule,parent): if not isinstance(rule, Action): raise Exception("Cannot use an ActionParser on a non-Action rule") Parser.__init__(self, rule, parent) self.actioned = False self.active = MakeParser(rule.items, self) def parse(self,token): disp = self.active.parse(token) self.bad = self.active.bad self.done = self.active.done if not self.actioned and not self.bad and self.done: self.rule.func(self) self.actioned = True return disp return '' # The Action's msg should contain at most a single %s, which will be filled # by the display of its sub-parser. It may have other text in its msg which # we'll want to display too. So we let the Rule do the work. def display(self): d = self.active.display() return self.rule.display([d])
class DispParser(Parser): def __init__(self,rule,parent): Parser.__init__(self, rule, parent) self.firstparse = True msg = self.rule.msg.split('%s') self.msg_start = msg[0] self.msg_middle = self.rule.msg.count('%s') > 0 self.msg_end = '' if len(msg) == 2: self.msg_end = msg[1] elif len(msg) > 2: raise Exception("DispParser %s found inappropriate msg '%s'" % (self.name, msg)) if len(self.rule.items) != 1: raise Exception("DispParser %s must have 1 item" % self.name) self.parser = MakeParser(self.rule.items[0], self) self.bad = self.parser.bad self.done = self.parser.done self.name = self.name % self.parser.name self.debug = [] def parse(self,token): if self.parser.name in self.debug: print "%s parsing %s" % (self.name, token) if self.bad: raise Exception("%s DispParser: cannot parse '%s'; already bad" % (self.name, token)) if not self.parser: self.parser = MakeParser(self.rule.items[0], self) disp = self.parser.parse(token) self.bad = self.parser.bad self.evil = self.parser.evil self.done = self.parser.done if self.bad: if self.parser.name in self.debug: print "%s went bad" % self.name if self.firstparse: if self.parser.name in self.debug: print "%s bad and firstparse" % self.name return '' # deny a bad first parse if self.parser.name in self.debug: print "%s bad and wasdone" % self.name if self.msg_middle: disp += copy(self.msg_end) else: disp = copy(self.msg_end) self.msg_end = '' if self.firstparse: if self.msg_middle: if self.parser.name in self.debug: print "%s firstparse yields '%s':'%s'" % (self.name, self.msg_start, disp) disp = copy(self.msg_start) + disp else: if self.parser.name in self.debug: print "%s firstparse yields '%s'" % (self.name, disp) disp = copy(self.msg_start) self.msg_start = '' self.firstparse = False if self.parser.name in self.debug: print "%s boring yields '%s'" % (self.name, disp) return disp def fakeEnd(self): if self.parser: return self.parser.fakeEnd() + self.msg_end return self.msg_end
class PlusParser(Parser): def __init__(self,rule,parent): Parser.__init__(self, rule, parent) self.active = None self.unconfirmed = '' self.neverGoBad = False self.debug = [] def parse(self,token): if self.name in self.debug: print print "%s parsing %s" % (self.name, token) logging.debug("%s PlusParser parsing token '%s'" % (self.name, token)) if not self.active: self.active = MakeParser(self.rule.items, self) self.bad = self.bad or self.active.bad if self.bad: raise Exception("%s PlusParser is bad" % self.name) wasdone = False if self.active.done: wasdone = True if self.name in self.debug: print " - wasdone" disp = self.active.parse(token) if self.name in self.debug: print " - received '%s'" % disp if wasdone and self.active.bad: # re-establish if self.name in self.debug: print "%s re-establishing" % self.name self.active = MakeParser(self.rule.items, self) self.unconfirmed = '' disp += self.parse(token) if self.name in self.debug: print "%s is re-established" % self.name print "%s evil=%s" % (self.name, self.evil) if self.neverGoBad and self.bad: raise Exception("%s StarParser has gone bad (eagerly)" % self.name) return disp self.bad = self.active.bad self.evil = self.active.evil self.done = self.active.done if self.name in self.debug: if self.evil: print "%s is evil, unconfirmed='%s'" % (self.name, self.unconfirmed) if self.done: self.unconfirmed = '' else: self.unconfirmed += disp if self.bad: if self.done: raise Exception("Plus noticed another terrible parser was both bad and done") if self.neverGoBad: raise Exception("%s StarParser has gone bad (eagerly)" % self.name) if self.unconfirmed: self.evil = True if self.name in self.debug: if self.evil: print "%s is evil2, unconfirmed='%s'" % (self.name, self.unconfirmed) if self.name in self.debug: print "%s evil=%s" % (self.name, self.evil) return disp def fakeEnd(self): if self.evil: raise Exception("%s is evil but fakeEnd() requested. Is that ok?" % self.name) if self.active: return self.active.fakeEnd() return ''