from itertools import count
def numbers():
for n in count():
yield str(n)
def terms():
def parens():
for exp in expressions():
yield "(" + exp + ")"
return alternate(numbers, parens)
def mul():
def mul2():
for a, b in combine(mul, terms):
yield a + "*" + b
return alternate(terms, mul2)
def add():
def add2():
for a, b in combine(add, mul):
yield a + "+" + b
return alternate(mul, add2)
expressions = add
def alternate(s, t):
x = s()
y = t()
while True:
yield x.next()
yield y.next()
def combine(s, t):
for n in count(1):
comb = [x for x in partial_combination(s, t, n)]
#print "comb", n, comb
if len(comb) == 0:
return
else:
for p in comb:
yield p
def take_first(s, n):
x = s()
for i in range(0, n):
yield x.next()
def partial_combination(s, t, n):
vals = [val for val in take_first(s, n)]
for i in range(len(vals), n):
vals.append(None)
vals.reverse()
ygen = t()
for x in vals:
try:
y = ygen.next()
if x is not None:
yield (x, y)
except:
if x is None: return
for e in expressions():
print e