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