| # 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 |