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