106 lines
3.0 KiB
Python
106 lines
3.0 KiB
Python
# Coroutine example: general coroutine transfers
|
|
#
|
|
# The program is a variation of a Simula 67 program due to Dahl & Hoare,
|
|
# (Dahl/Dijkstra/Hoare, Structured Programming; Academic Press, 1972)
|
|
# 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.tran(codisassembler, 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
|