func interpretToken(tok *kagome.Token) (string, category) {
	str := tok.Surface
	cat := unknown
	if tok.Class == kagome.KNOWN {
		fs := tok.Features()
		var (
			partOfSpeech  = fs[0]
			subClass1     = fs[1]
			subClass2     = fs[2]
			rootForm      = fs[6]
			pronunciation = fs[8]
		)
		str = pronunciation
		cat = morpheme
		switch partOfSpeech {
		case "フィラー", "記号":
			cat = meta
		case "助動詞":
			cat = auxiliary
		case "助詞":
			switch rootForm {
			case "は":
				str = "ハ"
			case "へ":
				str = "ヘ"
			}
		default:
			if subClass2 == "人名" {
				cat = personName
			} else if subClass1 == "固有名詞" {
				cat = properNoun
			}
		}
	} else {
		isSpace := strings.TrimSpace(str) == ""
		if isSpace {
			cat = meta
		}
	}
	return str, cat
}
interpretToken picks a pronunciation and category from a Kagome token.
package furigana
import (
	"bytes"
	"strings"
	"unicode/utf8"
	kagome "github.com/ikawaha/kagome.ipadic/tokenizer"
)
type category int
const (
	illegal category = iota
	meta
	morpheme
	auxiliary
	properNoun
	personName
	unknown
)
type typewriter struct {
	tokens  []kagome.Token
	result  string
	cur     int
	lastCat category
}
func newTypewriter(tokens []kagome.Token) *typewriter {
	return &typewriter{tokens, "", -1, illegal}
}
func (t *typewriter) Typewrite() string {
	if t.cur != -1 {
		return t.result
	}
	var buf bytes.Buffer
	for {
		sep, str := t.scanMorpheme()
		if str == "" {
			break
		}
		buf.WriteString(sep)
		buf.WriteString(str)
	}
	t.result = buf.String()
	return t.result
}
func (t *typewriter) scanMorpheme() (sep string, str string) {
	var buf bytes.Buffer
	tok := t.read()
	if tok == nil {
		return
	}
	str, cat := interpretToken(tok)
	if cat == unknown {
		str = mergeLongVowels(str, 0)
	}
	if t.lastCat == meta || t.lastCat == illegal {
		sep = ""
	} else if cat == personName && t.lastCat == personName {
		sep = " "
	}
	t.lastCat = cat
	coreLen := utf8.RuneCountInString(str)
	buf.WriteString(str)
	for {
		tok := t.read()
		if tok == nil {
			break
		}
		str, cat := interpretToken(tok)
		if cat == auxiliary {
			buf.WriteString(str)
		} else {
			t.unread()
			break
		}
	}
	str = buf.String()
	str = mergeLongVowels(str, coreLen)
	return sep, str
}
func (t *typewriter) read() *kagome.Token {
	var tok *kagome.Token
	for tok == nil || tok.Class == kagome.DUMMY {
		t.cur++
		if t.cur >= len(t.tokens) {
			return nil
		}
		tok = &t.tokens[t.cur]
	}
	return tok
}
func (t *typewriter) unread() {
	t.cur--
}