"""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()