blob: 0d59cb839bb5f59d39cdc512a78711d503e25725 [file] [log] [blame]
Guido van Rossumf4e13a42000-11-08 15:17:49 +00001# Coroutine example: general coroutine transfers
2#
3# The program is a variation of a Simula 67 program due to Dahl & Hoare,
Guido van Rossum27f9b842001-03-22 13:36:11 +00004# (Dahl/Dijkstra/Hoare, Structured Programming; Academic Press, 1972)
Guido van Rossumf4e13a42000-11-08 15:17:49 +00005# 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'):
Guido van Rossum27f9b842001-03-22 13:36:11 +000047 co.tran(codisassembler, line)
Guido van Rossumf4e13a42000-11-08 15:17:49 +000048
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