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