Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

SeminarHowToProgramIt/Pipe/VendingMachineParser.py

From ZeroWiki
#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()`