func (opts *affixOptions) parseSet(args []string) {
	if len(args) == 0 {
		return
	}
	encoding := strings.ToUpper(args[0])
	switch encoding {
	case EncodingUTF8,
		EncodingISO8859_1, EncodingISO8859_2, EncodingISO8859_3,
		EncodingISO8859_4, EncodingISO8859_5, EncodingISO8859_6,
		EncodingISO8859_7, EncodingISO8859_8, EncodingISO8859_9,
		EncodingISO8859_10,
		EncodingISO8859_13, EncodingISO8859_14, EncodingISO8859_15,
		EncodingKOI8R, EncodingKOI8U, EncodingCP1251,
		EncodingISCIIDevanagri:
		opts.encoding = encoding
	default:
		log.Printf("hunspell: invalid SET value %q\n", encoding)
	}
}
parseSet option from affix file.
package hunspell
import (
	"fmt"
	"io/ioutil"
	"log"
	"regexp"
	"strconv"
	"strings"
	"unicode/utf8"
	"github.com/shuLhan/share/lib/parser"
	libstrings "github.com/shuLhan/share/lib/strings"
)
type affixOptions struct {
	encoding string
	flag string
	isComplexPrefixes bool
	lang string
	ignore string
	afAliases []string
	amAliases []string
	keys []string
	try string
	noSuggest          []string       
	maxCompundSuggests int            
	maxNGramSuggests   int            
	maxDiff            int            
	isOnlyMaxDiff      bool           
	isNoSplitSugs      bool           
	isSugsWithDots     bool           
	reps               []replacement  
	charsMaps          []charsmap     
	warn               string         
	isForbidWarn       bool           
	breakOpts              []breakopt         
	compoundRules          []compoundRule     
	compoundMin            int                
	compoundFlag           string             
	compoundBegin          string             
	compoundLast           string             
	compoundMiddle         string             
	onlyInCompound         string             
	compoundPermitFlag     string             
	compoundForbidFlag     string             
	isCompoundMoreSuffixes bool               
	compoundRoot           string             
	compoundWordMax        int                
	isCheckCompoundDup     bool               
	isCheckCompoundRep     bool               
	isCheckCompoundCase    bool               
	isCheckCompoundTriple  bool               
	isSimplifiedTriple     bool               
	compoundPatterns       []compoundPattern  
	forceUCase             string             
	compoundSyllable       *compoundSyllable  
	syllableNum            string             
	prefixes map[string]*affix  
	suffixes map[string]*affix  
	circumfix     string        
	forbiddenWord string        
	isFullStrip   bool          
	keepCase      string        
	iconv         []conversion  
	oconv         []conversion  
	lemmaPresent  string        
	needAffix     string        
	pseudoRoot    string        
	substandard   string        
	wordchars     string        
	isCheckSharps bool          
}
func (opts *affixOptions) open(file string) (err error) {
	affcontent, err := ioutil.ReadFile(file)
	if err != nil {
		return fmt.Errorf("affixOptions.open: %w", err)
	}
	err = opts.load(string(affcontent))
	if err != nil {
		return err
	}
	return nil
}
func (opts *affixOptions) load(content string) (err error) {
	p := parser.New(content, "")
	lines := p.Lines()
	for x := 0; x < len(lines); x++ {
		if lines[x][0] == '#' {
			continue
		}
		tokens := libstrings.Split(lines[x], false, false)
		opt := strings.ToUpper(tokens[0])
		switch opt {
		case optSet:
			opts.parseSet(tokens[1:])
		case optFlag:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: FLAG: missing argument", x)
			}
			opts.parseFlag(tokens[1])
		case optComplexPrefixes:
			opts.isComplexPrefixes = true
		case optLang:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: LANG: missing argument", x)
			}
			opts.lang = strings.ToLower(tokens[1])
		case optIgnore:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: IGNORE: missing argument", x)
			}
			opts.ignore = tokens[1]
		case optAF:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: AF: missing argument", x)
			}
			err = opts.parseAF(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optAM:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: AM: missing argument", x)
			}
			err = opts.parseAM(tokens[1:])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optKey:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: KEY: missing argument", x)
			}
			opts.keys = strings.Split(tokens[1], "|")
		case optTry:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: TRY: missing argument", x)
			}
			opts.try = tokens[1]
		case optNoSuggest:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: NOSUGGEST: missing argument", x)
			}
			opts.noSuggest = append(opts.noSuggest, tokens[1])
		case optMaxCPDSuggest:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: missing MAXCPDSUGS argument", x)
			}
			opts.maxCompundSuggests, err = strconv.Atoi(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optMaxNGramSugs:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: MAXNGRAMSUGS: missing argument", x)
			}
			opts.maxNGramSuggests, err = strconv.Atoi(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optMaxDiff:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: MAXNGRAMSUGS: missing argument", x)
			}
			opts.maxDiff, err = strconv.Atoi(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
			if opts.maxDiff < 1 || opts.maxDiff > 10 {
				opts.maxDiff = 5
			}
		case optOnlyMaxDiff:
			opts.isOnlyMaxDiff = true
		case optNoSplitSugs:
			opts.isNoSplitSugs = true
		case optSugsWithDots:
			opts.isSugsWithDots = true
		case optRep:
			err = opts.parseRep(tokens[1:])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optMap:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: MAP: missing argument", x)
			}
			err = opts.parseMap(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optPhone:
		case optWarn:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: WARN: missing argument", x)
			}
			opts.warn = tokens[1]
		case optForbidWarn:
			opts.isForbidWarn = true
		case optBreak:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: BREAK: missing argument", x)
			}
			err = opts.parseBreak(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optCompoundRule:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d:, COMPOUNDRULE: missing argument", x)
			}
			err = opts.parseCompoundRule(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optCompoundMin:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: COMPOUNDMIN: missing argument", x)
			}
			opts.compoundMin, err = strconv.Atoi(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: COMPOUNDMIN: invalid argument %q", x, tokens[1])
			}
		case optCompoundFlag:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: COMPOUNDFLAG: missing argument", x)
			}
			opts.compoundFlag = tokens[1]
		case optCompoundBegin:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: COMPOUNDBEGIN: missing argument", x)
			}
			opts.compoundBegin = tokens[1]
		case optCompoundLast:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: COMPOUNDLAST: missing argument", x)
			}
			opts.compoundLast = tokens[1]
		case optCompoundMiddle:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: COMPOUNDMIDDLE: missing argument", x)
			}
			opts.compoundMiddle = tokens[1]
		case optOnlyInCompound:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: ONLYINCOMPOUND: missing argument", x)
			}
			opts.onlyInCompound = tokens[1]
		case optCompoundPermitFlag:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: COMPOUNDPERMITFLAG: missing argument", x)
			}
			opts.compoundPermitFlag = tokens[1]
		case optCompoundForbidFlags:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: COMPOUNDFORBIDFLAG: missing argument", x)
			}
			opts.compoundForbidFlag = tokens[1]
		case optCompoundMoreSuffixes:
			opts.isCompoundMoreSuffixes = true
		case optCompoundRoot:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: COMPOUNDROOT: missing argument", x)
			}
			opts.compoundRoot = tokens[1]
		case optCompoundWordMax:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: COMPOUNDWORDMAX: missing argument", x)
			}
			opts.compoundWordMax, err = strconv.Atoi(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: COMPOUNDWORDMAX: invalid argument %q", x, tokens[1])
			}
		case optCheckCompoundDup:
			opts.isCheckCompoundDup = true
		case optCheckCompoundRep:
			opts.isCheckCompoundRep = true
		case optCheckCompoundCase:
			opts.isCheckCompoundCase = true
		case optCheckCompoundTriple:
			opts.isCheckCompoundTriple = true
		case optSimplifiedTriple:
			opts.isSimplifiedTriple = true
		case optCheckCompoundPattern:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: CHECKCOMPOUNDPATTERN: missing argument", x)
			}
			err = opts.parseCheckCompoundPattern(tokens)
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optForceUcase:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: FORCEUCASE: missing argument", x)
			}
			opts.forceUCase = tokens[1]
		case optCompoundSyllable:
			if len(tokens) != 3 {
				return fmt.Errorf("line %d: COMPOUNDSYLLABLE: missing argument", x)
			}
			cs := &compoundSyllable{}
			cs.max, err = strconv.Atoi(tokens[1])
			if err != nil {
				return fmt.Errorf("line %d: COMPOUNDSYLLABLE: invalid argument %q: %s", x, tokens[1], err.Error())
			}
			cs.vowels = tokens[2]
			opts.compoundSyllable = cs
		case optSyllableNum:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: SYLLABLENUM: missing argument", x)
			}
			opts.syllableNum = tokens[1]
		case optPFX:
			if len(tokens) < 3 {
				return fmt.Errorf("line %d: PFX: missing arguments", x)
			}
			err = opts.parsePfx(tokens[1:])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optSFX:
			if len(tokens) < 3 {
				return fmt.Errorf("line %d: SFX: missing arguments", x)
			}
			err = opts.parseSfx(tokens[1:])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optCircumfix:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: CIRCUMFIX: missing argument", x)
			}
			opts.circumfix = tokens[1]
		case optForbiddenWord:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: FORBIDDENWORD: missing argument", x)
			}
			opts.forbiddenWord = tokens[1]
		case optFullStrip:
			opts.isFullStrip = true
		case optKeepCase:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: KEEPCASE: missing argument", x)
			}
			opts.keepCase = tokens[1]
		case optIconv:
			if len(tokens) == 1 {
				return fmt.Errorf("line %d: ICONV: missing argument", x)
			}
			err = opts.parseIconv(tokens[1:])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optOconv:
			if len(tokens) != 3 {
				return fmt.Errorf("line %d: OCONV: missing argument", x)
			}
			err = opts.parseOconv(tokens[1:])
			if err != nil {
				return fmt.Errorf("line %d: %s", x, err.Error())
			}
		case optLemmaPresent:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: LEMMA_PRESENT: missing argument", x)
			}
			opts.lemmaPresent = tokens[1]
		case optNeedAffix:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: NEEDAFFIX: missing argument", x)
			}
			opts.needAffix = tokens[1]
		case optPseudoRoot:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: PSEUDOROOT: missing argument", x)
			}
			opts.pseudoRoot = tokens[1]
		case optSubstandard:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: SUBSTANDARD: missing argument", x)
			}
			opts.substandard = tokens[1]
		case optWordChars:
			if len(tokens) != 2 {
				return fmt.Errorf("line %d: WORDCHARS: missing argument", x)
			}
			opts.wordchars = tokens[1]
		case optCheckSharps:
			opts.isCheckSharps = true
		default:
			log.Printf("line %d: unknown option %q\n", x, tokens[0])
		}
	}
	return nil
}