/Demo/threads/squasher.py

http://unladen-swallow.googlecode.com/ · Python · 105 lines · 62 code · 13 blank · 30 comment · 14 complexity · 4b8a7c84cac5c00f9742d5cf871b38e0 MD5 · raw file

  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. 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. # The program should print:
  23. # d = sqrt(b^2 - 4*a*c);twoa = 2*a; L = -b/twoa; R = d/twoa; A1 = L + R;
  24. #A2 = L - R
  25. #done
  26. # getline: delivers the next input line to its invoker
  27. # disassembler: grabs input lines from getline, and delivers them one
  28. # character at a time to squasher, also inserting a semicolon into
  29. # the stream between lines
  30. # squasher: grabs characters from disassembler and passes them on to
  31. # assembler, first replacing "**" with "^" and squashing runs of
  32. # whitespace
  33. # assembler: grabs characters from squasher and packs them into lines
  34. # with 72 character each, delivering each such line to putline;
  35. # when it sees a null byte, passes the last line to putline and
  36. # then kills all the coroutines
  37. # putline: grabs lines from assembler, and just prints them
  38. from Coroutine import *
  39. def getline(text):
  40. for line in string.splitfields(text, '\n'):
  41. co.tran(codisassembler, line)
  42. def disassembler():
  43. while 1:
  44. card = co.tran(cogetline)
  45. for i in range(len(card)):
  46. co.tran(cosquasher, card[i])
  47. co.tran(cosquasher, ';')
  48. def squasher():
  49. while 1:
  50. ch = co.tran(codisassembler)
  51. if ch == '*':
  52. ch2 = co.tran(codisassembler)
  53. if ch2 == '*':
  54. ch = '^'
  55. else:
  56. co.tran(coassembler, ch)
  57. ch = ch2
  58. if ch in ' \t':
  59. while 1:
  60. ch2 = co.tran(codisassembler)
  61. if ch2 not in ' \t':
  62. break
  63. co.tran(coassembler, ' ')
  64. ch = ch2
  65. co.tran(coassembler, ch)
  66. def assembler():
  67. line = ''
  68. while 1:
  69. ch = co.tran(cosquasher)
  70. if ch == '\0':
  71. break
  72. if len(line) == 72:
  73. co.tran(coputline, line)
  74. line = ''
  75. line = line + ch
  76. line = line + ' ' * (72 - len(line))
  77. co.tran(coputline, line)
  78. co.kill()
  79. def putline():
  80. while 1:
  81. line = co.tran(coassembler)
  82. print line
  83. import string
  84. co = Coroutine()
  85. cogetline = co.create(getline, test)
  86. coputline = co.create(putline)
  87. coassembler = co.create(assembler)
  88. codisassembler = co.create(disassembler)
  89. cosquasher = co.create(squasher)
  90. co.tran(coputline)
  91. print 'done'
  92. # end of example