Skip to content

Instantly share code, notes, and snippets.

@shintakezou
Created December 23, 2014 11:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shintakezou/88188591a1a856def7c4 to your computer and use it in GitHub Desktop.
Save shintakezou/88188591a1a856def7c4 to your computer and use it in GitHub Desktop.
Producer/Consumer with just a single goroutine
package main
import (
io "bufio"
"fmt"
"os"
"unicode"
)
type ControlFlow struct {
c byte
eof bool
}
// states of the FSM
const (
START = iota
IN_WORD
)
// token types/kinds
const (
WORD = iota
PUNCT
)
// ----
func decompressor(in *io.Reader, out_stream chan ControlFlow) {
for {
b, err := in.ReadByte()
if err != nil {
break
} else if b == 0xFF {
len, _ := in.ReadByte() // ignore errors...
real_len := int(len) + 1
c, _ := in.ReadByte()
for ; real_len >= 0; real_len-- {
out_stream <- ControlFlow{c, false}
}
} else {
out_stream <- ControlFlow{b, false}
}
}
out_stream <- ControlFlow{0, true}
}
func parser(c chan ControlFlow) {
var in ControlFlow
var state int
var s string
state = START
for {
in = <-c
if in.eof {
break
}
switch state {
case IN_WORD:
if unicode.IsLetter(rune(in.c)) {
add_to_token(in.c, &s)
continue
}
got_token(WORD, &s)
state = START
fallthrough
case START:
add_to_token(in.c, &s)
if unicode.IsLetter(rune(in.c)) {
state = IN_WORD
} else {
got_token(PUNCT, &s)
}
break
}
}
if state == IN_WORD {
got_token(WORD, &s)
}
}
func add_to_token(a byte, s *string) {
*s += string(a)
}
func got_token(kind int, s *string) {
switch kind {
case WORD:
fmt.Printf("WORD: %s\n", *s)
break
case PUNCT:
fmt.Printf("PUNCT: %s\n", *s)
break
}
*s = ""
}
func main() {
in := io.NewReader(os.Stdin)
ch := make(chan ControlFlow)
go decompressor(in, ch)
parser(ch)
}
@shintakezou
Copy link
Author

Comments and best-go-practices or simply best-practices suggestions are welcome of course.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment