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 15 test = """\ 16 d = sqrt(b**2 - 4*a*c) 17 twoa = 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 43 from Coroutine import * 44 45 def getline(text): 46 for line in string.splitfields(text, '\n'): 47 co.tran(codisassembler, line) 48 49 def 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 56 def 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 75 def 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 89 def putline(): 90 while 1: 91 line = co.tran(coassembler) 92 print line 93 94 import string 95 co = Coroutine() 96 cogetline = co.create(getline, test) 97 coputline = co.create(putline) 98 coassembler = co.create(assembler) 99 codisassembler = co.create(disassembler) 100 cosquasher = co.create(squasher) 101 102 co.tran(coputline) 103 print 'done' 104 105 # end of example 106