"""Say number due to language specific rules""" import re import os import sys from itertools import imap class Action: """Bogus action, does nothing""" def __init__(self): """Bogus init""" pass def act(self, number, ruletable): """Does nothing""" pass class WriteAction: """The simplest action, yields param with which it was constructed""" def __init__(self, what): """Saves what for future use""" self.what = what def act(self, _number, _ruletable): """Yields previously saved param""" yield self.what class NumberAction: """Yields number constructed from source number and additional suffix""" def __init__(self, index, num): """Saves index and num for future use. index -- index of char, that should be extracted from number num -- additional suffix """ self.index = index self.num = num def act(self, number, _ruletable): """Yields char extracted from source number concatenated with suffix """ yield number[int(self.index)] + self.num class RecursiveAction: """Does recursive processing of number, constructed from list of indexes and additional suffix""" def __init__(self, indexes, num): """Saves indexes and num for future use. indexes -- list of indexes, that should be used for extracting chars from number num -- additional suffix """ self.indexes = indexes self.num = num def act(self, number, ruletable): """Recursively parses constructed number with same rules""" for x in ruletable.parse(''.join(imap (lambda x:number[int(x)], self.indexes)) + self.num): yield x class RuleTable: """Holds rules, provides ability to add new rules from string representation and ability for parsing numbers""" def __init__(self, lines): """Uses lines for rules creation""" self.rules = [] self.recreate(lines) def recreate(self, lines): """Parses lines and creates internal representation of rules and actions""" self.rules = [] for x in lines: left, right = x.split(':', 1) expr = re.compile('^' + left + '$') action_list = right.split(';') actions = [] for y in action_list: action = None if y[:9] == 'recursive': params = y[10:-1].split('|', 1) if len(params) == 1: action = RecursiveAction(params[0].split(','), '') else: action = RecursiveAction(params[0].split(','), params[1]) elif y[:6] == 'number': params = y[7:-1].split('|', 1) if len(params)==1: action = NumberAction(params[0], '') else: action = NumberAction(params[0], params[1]) else: action = WriteAction(y) actions.append(action) self.rules.append((expr, actions)) def parse(self, number): """Parses numbers and yields fundamental parts of number""" for (pattern, actions) in self.rules: if pattern.match(number): for x in actions: for y in x.act(number, self): yield y return def main(): """Main function""" if len(sys.argv) < 3: sys.exit(0) conf_file = os.path.normpath(os.path.dirname(__file__)) + '/'+sys.argv[2] lines = open(conf_file,'r').readlines() ruletable = RuleTable(imap(lambda x: x.strip(), lines)) try: while True: x = raw_input() if not x.strip(): break except: pass sys.stdout.write('EXEC NOOP StartPySayNum\n') playstr = '' for x in ruletable.parse(sys.argv[1]): if playstr: playstr += '&' playstr += 'digits/%s' % (x,) sys.stdout.write('EXEC PLAYBACK ' + playstr) sys.stdout.flush() x = raw_input() if __name__ == "__main__": main()