#VendingMachineParser.py import shlex,sys from cStringIO import StringIO from VendingMachine import * # //putCoin # //pushButton # //verifyCoin # //verifyButton """ class VendingMachine: def putCoin(self, anAmount): print '%d inserted' % anAmount def pushButton(self, aButtonType): print aButtonType + ' pushed' def verifyCoin(self, anAmount): print anAmount def verifyButton(self, aStatus): print aStatus """ v=VendingMachine() class VendingCmd: def __init__(self,cmd,**kwargs): self.cmd = cmd self.vm=v self.__dict__.update(kwargs) def __repr__(self): s = '%s(' % self.cmd for item in self.__dict__.items(): if item[0] != 'cmd': s += ' %s=%s' % item return s + ' )' def action(self): raise NotImplementedError class PutCmd(VendingCmd): def action(self): self.amount=self.arg self.vm.putCoin(self.amount) class PushCmd(VendingCmd): def action(self): self.buttonType = self.arg self.vm.pushButton(self.buttonType) class VerifyMoneyCmd(VendingCmd): def action(self): print self.vm.verifyCoin(self.amount) class VerifyButtonCmd(VendingCmd): def action(self): print self.vm.verifyButton(self.status) class Parser: def __init__(self,aStream=sys.stderr): self.outstream=aStream def next_token(self): tok = self.lexer.get_token() if not tok: self.err('Unexpected end of file') return tok def next_number(self,func=int): tok = self.next_token() if tok: try: tok = func(tok) except ValueError: return self.err('Expected a number, not '+tok) return tok def next_money(self): num=self.next_number() if num not in (10,50,100,500,1000): return self.err('Unexpected money type') return num def next_button(self): tok=self.lexer.get_token() if tok not in ('black','white','sugar_black','sugar_white'): return self.err('Unexpected button type') return tok def err(self,msg): self.outstream.write(self.lexer.error_leader()+msg+'\n') def parse_put(self): money = self.next_money() if money: return PutCmd('put',arg=money) def parse_push(self): button=self.next_button() if button: return PushCmd('push',arg=button) def parse_verify(self): verify=self.next_verify() if verify=='button': status=self.next_status() return VerifyButtonCmd('verify', arg=verify, status=status ) else: money = self.next_money() return VerifyMoneyCmd('verify', arg=verify, amount=money ) def next_status(self): tok=self.lexer.get_token() if tok not in ('on', 'off'): return self.err('Unexpected button status') return tok def next_verify(self): tok=self.lexer.get_token() if tok not in ('money', 'button'): return self.err('Unexpected verify type') # print tok return tok def parse(self,aString=None,aStream=None,aName=None): if aString: aStream=StringIO(aString) lexer=shlex.shlex(aStream,aName) lexer.source = 'include' lexer.wordchars += '.,-' self.lexer=lexer cmds = [] while 1: tok = lexer.get_token() if not tok: break try: parser = getattr(self,'parse_%s'%tok) except: self.err('Unknown command: '+tok) continue cmd=parser() if cmd is None: continue cmds.append(cmd) return cmds if __name__=='__main__': err=StringIO() p=Parser(err) cmds=p.parse("put 10 put 50 put 1000") print cmds print `err.getvalue()`