1# Coroutine example: general coroutine transfers 2# 3# The program is a variation of a Simula 67 program due to Dahl & Hoare, 4# (Dahl/Dijkstra/Hoare, Structured Programming; Academic Press, 1972) 5# who in turn credit the original example to Conway. 6# 7# We have a number of input lines, terminated by a 0 byte. The problem 8# is to squash them together into output lines containing 72 characters 9# each. A semicolon must be added between input lines. Runs of blanks 10# and tabs in input lines must be squashed into single blanks. 11# Occurrences of "**" in input lines must be replaced by "^". 12# 13# Here's a test case: 14 15test = """\ 16 d = sqrt(b**2 - 4*a*c) 17twoa = 2*a 18 L = -b/twoa 19 R = d/twoa 20 A1 = L + R 21 A2 = L - R\0 22""" 23 24# The program should print: 25 26# d = sqrt(b^2 - 4*a*c);twoa = 2*a; L = -b/twoa; R = d/twoa; A1 = L + R; 27#A2 = L - R 28#done 29 30# getline: delivers the next input line to its invoker 31# disassembler: grabs input lines from getline, and delivers them one 32# character at a time to squasher, also inserting a semicolon into 33# the stream between lines 34# squasher: grabs characters from disassembler and passes them on to 35# assembler, first replacing "**" with "^" and squashing runs of 36# whitespace 37# assembler: grabs characters from squasher and packs them into lines 38# with 72 character each, delivering each such line to putline; 39# when it sees a null byte, passes the last line to putline and 40# then kills all the coroutines 41# putline: grabs lines from assembler, and just prints them 42 43from Coroutine import * 44 45def getline(text): 46 for line in string.splitfields(text, '\n'): 47 co.tran(codisassembler, line) 48 49def disassembler(): 50 while 1: 51 card = co.tran(cogetline) 52 for i in range(len(card)): 53 co.tran(cosquasher, card[i]) 54 co.tran(cosquasher, ';') 55 56def squasher(): 57 while 1: 58 ch = co.tran(codisassembler) 59 if ch == '*': 60 ch2 = co.tran(codisassembler) 61 if ch2 == '*': 62 ch = '^' 63 else: 64 co.tran(coassembler, ch) 65 ch = ch2 66 if ch in ' \t': 67 while 1: 68 ch2 = co.tran(codisassembler) 69 if ch2 not in ' \t': 70 break 71 co.tran(coassembler, ' ') 72 ch = ch2 73 co.tran(coassembler, ch) 74 75def assembler(): 76 line = '' 77 while 1: 78 ch = co.tran(cosquasher) 79 if ch == '\0': 80 break 81 if len(line) == 72: 82 co.tran(coputline, line) 83 line = '' 84 line = line + ch 85 line = line + ' ' * (72 - len(line)) 86 co.tran(coputline, line) 87 co.kill() 88 89def putline(): 90 while 1: 91 line = co.tran(coassembler) 92 print line 93 94import string 95co = Coroutine() 96cogetline = co.create(getline, test) 97coputline = co.create(putline) 98coassembler = co.create(assembler) 99codisassembler = co.create(disassembler) 100cosquasher = co.create(squasher) 101 102co.tran(coputline) 103print 'done' 104 105# end of example 106