RosettaCodeData/Task/Odd-word-problem/Go/odd-word-problem-3.go

90 lines
1.9 KiB
Go

package main
import (
"bytes"
"fmt"
"io"
"os"
"unicode"
)
func main() {
owp(os.Stdout, bytes.NewBufferString("what,is,the;meaning,of:life."))
fmt.Println()
owp(os.Stdout, bytes.NewBufferString("we,are;not,in,kansas;any,more."))
fmt.Println()
}
type Coroutine struct {
out <-chan Coroutine
in chan<- byte
}
func owp(dst io.Writer, src io.Reader) {
byte_in := func () (byte, error) {
bs := make([]byte, 1)
_, err := src.Read(bs)
return bs[0], err
}
byte_out := func (b byte) { dst.Write([]byte{b}) }
var f, r Coroutine
f = func () Coroutine {
out := make(chan Coroutine)
in := make(chan byte)
var fwd func (byte) byte
fwd = func (c byte) (z byte) {
if unicode.IsLetter(rune(c)) {
byte_out(c)
out <- f
z = fwd(<- in)
} else {
z = c
}
return
}
go func () {
for {
x, ok := <- in
if !ok { break }
byte_out(fwd(x))
out <- r
}
} ()
return Coroutine{ out, in }
} ()
r = func () Coroutine {
out := make(chan Coroutine)
in := make(chan byte)
var rev func (byte) byte
rev = func (c byte) (z byte) {
if unicode.IsLetter(rune(c)) {
out <- r
z = rev(<- in)
byte_out(c)
} else {
z = c
}
return
}
go func () {
for {
x, ok := <- in
if !ok { break }
byte_out(rev(x))
out <- f
}
} ()
return Coroutine{ out, in }
} ()
for coro := f; ; coro = <- coro.out {
c, err := byte_in()
if err != nil { break }
coro.in <- c
}
close(f.in)
close(r.in)
}