105 lines
2.9 KiB
Python
105 lines
2.9 KiB
Python
|
# Coroutine example: general coroutine transfers
|
||
|
#
|
||
|
# The program is a variation of a Simula 67 program due to Dahl & Hoare,
|
||
|
# who in turn credit the original example to Conway.
|
||
|
#
|
||
|
# We have a number of input lines, terminated by a 0 byte. The problem
|
||
|
# is to squash them together into output lines containing 72 characters
|
||
|
# each. A semicolon must be added between input lines. Runs of blanks
|
||
|
# and tabs in input lines must be squashed into single blanks.
|
||
|
# Occurrences of "**" in input lines must be replaced by "^".
|
||
|
#
|
||
|
# Here's a test case:
|
||
|
|
||
|
test = """\
|
||
|
d = sqrt(b**2 - 4*a*c)
|
||
|
twoa = 2*a
|
||
|
L = -b/twoa
|
||
|
R = d/twoa
|
||
|
A1 = L + R
|
||
|
A2 = L - R\0
|
||
|
"""
|
||
|
|
||
|
# The program should print:
|
||
|
|
||
|
# d = sqrt(b^2 - 4*a*c);twoa = 2*a; L = -b/twoa; R = d/twoa; A1 = L + R;
|
||
|
#A2 = L - R
|
||
|
#done
|
||
|
|
||
|
# getline: delivers the next input line to its invoker
|
||
|
# disassembler: grabs input lines from getline, and delivers them one
|
||
|
# character at a time to squasher, also inserting a semicolon into
|
||
|
# the stream between lines
|
||
|
# squasher: grabs characters from disassembler and passes them on to
|
||
|
# assembler, first replacing "**" with "^" and squashing runs of
|
||
|
# whitespace
|
||
|
# assembler: grabs characters from squasher and packs them into lines
|
||
|
# with 72 character each, delivering each such line to putline;
|
||
|
# when it sees a null byte, passes the last line to putline and
|
||
|
# then kills all the coroutines
|
||
|
# putline: grabs lines from assembler, and just prints them
|
||
|
|
||
|
from Coroutine import *
|
||
|
|
||
|
def getline(text):
|
||
|
for line in string.splitfields(text, '\n'):
|
||
|
co.back(line)
|
||
|
|
||
|
def disassembler():
|
||
|
while 1:
|
||
|
card = co.tran(cogetline)
|
||
|
for i in range(len(card)):
|
||
|
co.tran(cosquasher, card[i])
|
||
|
co.tran(cosquasher, ';')
|
||
|
|
||
|
def squasher():
|
||
|
while 1:
|
||
|
ch = co.tran(codisassembler)
|
||
|
if ch == '*':
|
||
|
ch2 = co.tran(codisassembler)
|
||
|
if ch2 == '*':
|
||
|
ch = '^'
|
||
|
else:
|
||
|
co.tran(coassembler, ch)
|
||
|
ch = ch2
|
||
|
if ch in ' \t':
|
||
|
while 1:
|
||
|
ch2 = co.tran(codisassembler)
|
||
|
if ch2 not in ' \t':
|
||
|
break
|
||
|
co.tran(coassembler, ' ')
|
||
|
ch = ch2
|
||
|
co.tran(coassembler, ch)
|
||
|
|
||
|
def assembler():
|
||
|
line = ''
|
||
|
while 1:
|
||
|
ch = co.tran(cosquasher)
|
||
|
if ch == '\0':
|
||
|
break
|
||
|
if len(line) == 72:
|
||
|
co.tran(coputline, line)
|
||
|
line = ''
|
||
|
line = line + ch
|
||
|
line = line + ' ' * (72 - len(line))
|
||
|
co.tran(coputline, line)
|
||
|
co.kill()
|
||
|
|
||
|
def putline():
|
||
|
while 1:
|
||
|
line = co.tran(coassembler)
|
||
|
print line
|
||
|
|
||
|
import string
|
||
|
co = Coroutine()
|
||
|
cogetline = co.create(getline, test)
|
||
|
coputline = co.create(putline)
|
||
|
coassembler = co.create(assembler)
|
||
|
codisassembler = co.create(disassembler)
|
||
|
cosquasher = co.create(squasher)
|
||
|
|
||
|
co.tran(coputline)
|
||
|
print 'done'
|
||
|
|
||
|
# end of example
|