func typeToInt(token string) (uint16, bool) {
	offset := 4
	if len(token) < offset+1 {
		return 0, false
	}
	typ, err := strconv.ParseUint(token[offset:], 10, 16)
	if err != nil {
		return 0, false
	}
	return uint16(typ), true
}
Extract the rr number from TYPExxx
package dns
import (
	"io"
	"log"
	"os"
	"strconv"
	"strings"
)
type debugging bool
const debug debugging = false
func (d debugging) Printf(format string, args ...interface{}) {
	if d {
		log.Printf(format, args...)
	}
}
const maxTok = 2048  
const maxUint16 = 1<<16 - 1
const (
	zEOF = iota
	zString
	zBlank
	zQuote
	zNewline
	zRrtpe
	zOwner
	zClass
	zDirOrigin    
	zDirTtl       
	zDirInclude   
	zDirGenerate  
	zValue
	zKey
	zExpectOwnerDir       
	zExpectOwnerBl        
	zExpectAny            
	zExpectAnyNoClass     
	zExpectAnyNoClassBl   
	zExpectAnyNoTtl       
	zExpectAnyNoTtlBl     
	zExpectRrtype         
	zExpectRrtypeBl       
	zExpectRdata          
	zExpectDirTtlBl       
	zExpectDirTtl         
	zExpectDirOriginBl    
	zExpectDirOrigin      
	zExpectDirIncludeBl   
	zExpectDirInclude     
	zExpectDirGenerate    
	zExpectDirGenerateBl  
)
type ParseError struct {
	file string
	err  string
	lex  lex
}
func (e *ParseError) Error() (s string) {
	if e.file != "" {
		s = e.file + ": "
	}
	s += "dns: " + e.err + ": " + strconv.QuoteToASCII(e.lex.token) + " at line: " +
		strconv.Itoa(e.lex.line) + ":" + strconv.Itoa(e.lex.column)
	return
}
type lex struct {
	token      string  
	tokenUpper string  
	length     int     
	err        bool    
	value      uint8   
	line       int     
	column     int     
	torc       uint16  
	comment    string  
}
type Token struct {
	RR
	Error *ParseError
	Comment string
}
func NewRR(s string) (RR, error) {
	if len(s) > 0 && s[len(s)-1] != '\n' {  
		return ReadRR(strings.NewReader(s+"\n"), "")
	}
	return ReadRR(strings.NewReader(s), "")
}
func ReadRR(q io.Reader, filename string) (RR, error) {
	r := <-parseZoneHelper(q, ".", filename, 1)
	if r == nil {
		return nil, nil
	}
	if r.Error != nil {
		return nil, r.Error
	}
	return r.RR, nil
}
func ParseZone(r io.Reader, origin, file string) chan *Token {
	return parseZoneHelper(r, origin, file, 10000)
}
func parseZoneHelper(r io.Reader, origin, file string, chansize int) chan *Token {
	t := make(chan *Token, chansize)
	go parseZone(r, origin, file, t, 0)
	return t
}
func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
	defer func() {
		if include == 0 {
			close(t)
		}
	}()
	s := scanInit(r)
	c := make(chan lex)
	go zlexer(s, c)
	if origin == "" {
		origin = "."
	}
	origin = Fqdn(origin)
	if _, ok := IsDomainName(origin); !ok {
		t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
		return
	}
	st := zExpectOwnerDir  
	var h RR_Header
	var defttl uint32 = defaultTtl
	var prevName string
	for l := range c {
		if l.err == true {
			t <- &Token{Error: &ParseError{f, l.token, l}}
			return
		}
		switch st {
		case zExpectOwnerDir:
			h.Ttl = defttl
			h.Class = ClassINET
			switch l.value {
			case zNewline:
				st = zExpectOwnerDir
			case zOwner:
				h.Name = l.token
				if l.token[0] == '@' {
					h.Name = origin
					prevName = h.Name
					st = zExpectOwnerBl
					break
				}
				if h.Name[l.length-1] != '.' {
					h.Name = appendOrigin(h.Name, origin)
				}
				_, ok := IsDomainName(l.token)
				if !ok {
					t <- &Token{Error: &ParseError{f, "bad owner name", l}}
					return
				}
				prevName = h.Name
				st = zExpectOwnerBl
			case zDirTtl:
				st = zExpectDirTtlBl
			case zDirOrigin:
				st = zExpectDirOriginBl
			case zDirInclude:
				st = zExpectDirIncludeBl
			case zDirGenerate:
				st = zExpectDirGenerateBl
			case zRrtpe:
				h.Name = prevName
				h.Rrtype = l.torc
				st = zExpectRdata
			case zClass:
				h.Name = prevName
				h.Class = l.torc
				st = zExpectAnyNoClassBl
			case zBlank:
			case zString:
				ttl, ok := stringToTtl(l.token)
				if !ok {
					t <- &Token{Error: &ParseError{f, "not a TTL", l}}
					return
				}
				h.Ttl = ttl
				st = zExpectAnyNoTtlBl
			default:
				t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}}
				return
			}
		case zExpectDirIncludeBl:
			if l.value != zBlank {
				t <- &Token{Error: &ParseError{f, "no blank after $INCLUDE-directive", l}}
				return
			}
			st = zExpectDirInclude
		case zExpectDirInclude:
			if l.value != zString {
				t <- &Token{Error: &ParseError{f, "expecting $INCLUDE value, not this...", l}}
				return
			}
			neworigin := origin  
			l := <-c
			switch l.value {
			case zBlank:
				l := <-c
				if l.value == zString {
					if _, ok := IsDomainName(l.token); !ok || l.length == 0 || l.err {
						t <- &Token{Error: &ParseError{f, "bad origin name", l}}
						return
					}
					if l.token[l.length-1] != '.' {
						if origin != "." {  
							neworigin = l.token + "." + origin
						} else {
							neworigin = l.token + origin
						}
					} else {
						neworigin = l.token
					}
				}
			case zNewline, zEOF:
			default:
				t <- &Token{Error: &ParseError{f, "garbage after $INCLUDE", l}}
				return
			}
			r1, e1 := os.Open(l.token)
			if e1 != nil {
				t <- &Token{Error: &ParseError{f, "failed to open `" + l.token + "'", l}}
				return
			}
			if include+1 > 7 {
				t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
				return
			}
			parseZone(r1, l.token, neworigin, t, include+1)
			st = zExpectOwnerDir
		case zExpectDirTtlBl:
			if l.value != zBlank {
				t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}}
				return
			}
			st = zExpectDirTtl
		case zExpectDirTtl:
			if l.value != zString {
				t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
				return
			}
			if e, _ := slurpRemainder(c, f); e != nil {
				t <- &Token{Error: e}
				return
			}
			ttl, ok := stringToTtl(l.token)
			if !ok {
				t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
				return
			}
			defttl = ttl
			st = zExpectOwnerDir
		case zExpectDirOriginBl:
			if l.value != zBlank {
				t <- &Token{Error: &ParseError{f, "no blank after $ORIGIN-directive", l}}
				return
			}
			st = zExpectDirOrigin
		case zExpectDirOrigin:
			if l.value != zString {
				t <- &Token{Error: &ParseError{f, "expecting $ORIGIN value, not this...", l}}
				return
			}
			if e, _ := slurpRemainder(c, f); e != nil {
				t <- &Token{Error: e}
			}
			if _, ok := IsDomainName(l.token); !ok {
				t <- &Token{Error: &ParseError{f, "bad origin name", l}}
				return
			}
			if l.token[l.length-1] != '.' {
				if origin != "." {  
					origin = l.token + "." + origin
				} else {
					origin = l.token + origin
				}
			} else {
				origin = l.token
			}
			st = zExpectOwnerDir
		case zExpectDirGenerateBl:
			if l.value != zBlank {
				t <- &Token{Error: &ParseError{f, "no blank after $GENERATE-directive", l}}
				return
			}
			st = zExpectDirGenerate
		case zExpectDirGenerate:
			if l.value != zString {
				t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}}
				return
			}
			if errMsg := generate(l, c, t, origin); errMsg != "" {
				t <- &Token{Error: &ParseError{f, errMsg, l}}
				return
			}
			st = zExpectOwnerDir
		case zExpectOwnerBl:
			if l.value != zBlank {
				t <- &Token{Error: &ParseError{f, "no blank after owner", l}}
				return
			}
			st = zExpectAny
		case zExpectAny:
			switch l.value {
			case zRrtpe:
				h.Rrtype = l.torc
				st = zExpectRdata
			case zClass:
				h.Class = l.torc
				st = zExpectAnyNoClassBl
			case zString:
				ttl, ok := stringToTtl(l.token)
				if !ok {
					t <- &Token{Error: &ParseError{f, "not a TTL", l}}
					return
				}
				h.Ttl = ttl
				st = zExpectAnyNoTtlBl
			default:
				t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
				return
			}
		case zExpectAnyNoClassBl:
			if l.value != zBlank {
				t <- &Token{Error: &ParseError{f, "no blank before class", l}}
				return
			}
			st = zExpectAnyNoClass
		case zExpectAnyNoTtlBl:
			if l.value != zBlank {
				t <- &Token{Error: &ParseError{f, "no blank before TTL", l}}
				return
			}
			st = zExpectAnyNoTtl
		case zExpectAnyNoTtl:
			switch l.value {
			case zClass:
				h.Class = l.torc
				st = zExpectRrtypeBl
			case zRrtpe:
				h.Rrtype = l.torc
				st = zExpectRdata
			default:
				t <- &Token{Error: &ParseError{f, "expecting RR type or class, not this...", l}}
				return
			}
		case zExpectAnyNoClass:
			switch l.value {
			case zString:
				ttl, ok := stringToTtl(l.token)
				if !ok {
					t <- &Token{Error: &ParseError{f, "not a TTL", l}}
					return
				}
				h.Ttl = ttl
				st = zExpectRrtypeBl
			case zRrtpe:
				h.Rrtype = l.torc
				st = zExpectRdata
			default:
				t <- &Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}}
				return
			}
		case zExpectRrtypeBl:
			if l.value != zBlank {
				t <- &Token{Error: &ParseError{f, "no blank before RR type", l}}
				return
			}
			st = zExpectRrtype
		case zExpectRrtype:
			if l.value != zRrtpe {
				t <- &Token{Error: &ParseError{f, "unknown RR type", l}}
				return
			}
			h.Rrtype = l.torc
			st = zExpectRdata
		case zExpectRdata:
			r, e, c1 := setRR(h, c, origin, f)
			if e != nil {
				if e.lex.token == "" && e.lex.value == 0 {
					e.lex = l  
				}
				t <- &Token{Error: e}
				return
			}
			t <- &Token{RR: r, Comment: c1}
			st = zExpectOwnerDir
		}
	}
}
func zlexer(s *scan, c chan lex) {
	var l lex
	str := make([]byte, maxTok)  
	stri := 0                    
	com := make([]byte, maxTok)  
	comi := 0
	quote := false
	escape := false
	space := false
	commt := false
	rrtype := false
	owner := true
	brace := 0
	x, err := s.tokenText()
	defer close(c)
	for err == nil {
		l.column = s.position.Column
		l.line = s.position.Line
		if stri >= maxTok {
			l.token = "token length insufficient for parsing"
			l.err = true
			debug.Printf("[%+v]", l.token)
			c <- l
			return
		}
		if comi >= maxTok {
			l.token = "comment length insufficient for parsing"
			l.err = true
			debug.Printf("[%+v]", l.token)
			c <- l
			return
		}
		switch x {
		case ' ', '\t':
			if escape {
				escape = false
				str[stri] = x
				stri++
				break
			}
			if quote {
				str[stri] = x
				stri++
				break
			}
			if commt {
				com[comi] = x
				comi++
				break
			}
			if stri == 0 {
			} else if owner {
				l.value = zOwner
				l.token = string(str[:stri])
				l.tokenUpper = strings.ToUpper(l.token)
				l.length = stri
				switch l.tokenUpper {
				case "$TTL":
					l.value = zDirTtl
				case "$ORIGIN":
					l.value = zDirOrigin
				case "$INCLUDE":
					l.value = zDirInclude
				case "$GENERATE":
					l.value = zDirGenerate
				}
				debug.Printf("[7 %+v]", l.token)
				c <- l
			} else {
				l.value = zString
				l.token = string(str[:stri])
				l.tokenUpper = strings.ToUpper(l.token)
				l.length = stri
				if !rrtype {
					if t, ok := StringToType[l.tokenUpper]; ok {
						l.value = zRrtpe
						l.torc = t
						rrtype = true
					} else {
						if strings.HasPrefix(l.tokenUpper, "TYPE") {
							t, ok := typeToInt(l.token)
							if !ok {
								l.token = "unknown RR type"
								l.err = true
								c <- l
								return
							}
							l.value = zRrtpe
							l.torc = t
						}
					}
					if t, ok := StringToClass[l.tokenUpper]; ok {
						l.value = zClass
						l.torc = t
					} else {
						if strings.HasPrefix(l.tokenUpper, "CLASS") {
							t, ok := classToInt(l.token)
							if !ok {
								l.token = "unknown class"
								l.err = true
								c <- l
								return
							}
							l.value = zClass
							l.torc = t
						}
					}
				}
				debug.Printf("[6 %+v]", l.token)
				c <- l
			}
			stri = 0
			if !space && !commt {
				l.value = zBlank
				l.token = " "
				l.length = 1
				debug.Printf("[5 %+v]", l.token)
				c <- l
			}
			owner = false
			space = true
		case ';':
			if escape {
				escape = false
				str[stri] = x
				stri++
				break
			}
			if quote {
				str[stri] = x
				stri++
				break
			}
			if stri > 0 {
				l.value = zString
				l.token = string(str[:stri])
				l.tokenUpper = strings.ToUpper(l.token)
				l.length = stri
				debug.Printf("[4 %+v]", l.token)
				c <- l
				stri = 0
			}
			commt = true
			com[comi] = ';'
			comi++
		case '\r':
			escape = false
			if quote {
				str[stri] = x
				stri++
				break
			}
		case '\n':
			escape = false
			if quote {
				str[stri] = x
				stri++
				break
			}
			if commt {
				commt = false
				rrtype = false
				stri = 0
				if brace == 0 {
					owner = true
					owner = true
					l.value = zNewline
					l.token = "\n"
					l.tokenUpper = l.token
					l.length = 1
					l.comment = string(com[:comi])
					debug.Printf("[3 %+v %+v]", l.token, l.comment)
					c <- l
					l.comment = ""
					comi = 0
					break
				}
				com[comi] = ' '  
				comi++
				break
			}
			if brace == 0 {
				if stri != 0 {
					l.value = zString
					l.token = string(str[:stri])
					l.tokenUpper = strings.ToUpper(l.token)
					l.length = stri
					if !rrtype {
						if t, ok := StringToType[l.tokenUpper]; ok {
							l.value = zRrtpe
							l.torc = t
							rrtype = true
						}
					}
					debug.Printf("[2 %+v]", l.token)
					c <- l
				}
				l.value = zNewline
				l.token = "\n"
				l.tokenUpper = l.token
				l.length = 1
				debug.Printf("[1 %+v]", l.token)
				c <- l
				stri = 0
				commt = false
				rrtype = false
				owner = true
				comi = 0
			}
		case '\\':
			if commt {
				com[comi] = x
				comi++
				break
			}
			if escape {
				str[stri] = x
				stri++
				escape = false
				break
			}
			str[stri] = x
			stri++
			escape = true
		case '"':
			if commt {
				com[comi] = x
				comi++
				break
			}
			if escape {
				str[stri] = x
				stri++
				escape = false
				break
			}
			space = false
			if stri != 0 {
				l.value = zString
				l.token = string(str[:stri])
				l.tokenUpper = strings.ToUpper(l.token)
				l.length = stri
				debug.Printf("[%+v]", l.token)
				c <- l
				stri = 0
			}
			l.value = zQuote
			l.token = "\""
			l.tokenUpper = l.token
			l.length = 1
			c <- l
			quote = !quote
		case '(', ')':
			if commt {
				com[comi] = x
				comi++
				break
			}
			if escape {
				str[stri] = x
				stri++
				escape = false
				break
			}
			if quote {
				str[stri] = x
				stri++
				break
			}
			switch x {
			case ')':
				brace--
				if brace < 0 {
					l.token = "extra closing brace"
					l.tokenUpper = l.token
					l.err = true
					debug.Printf("[%+v]", l.token)
					c <- l
					return
				}
			case '(':
				brace++
			}
		default:
			escape = false
			if commt {
				com[comi] = x
				comi++
				break
			}
			str[stri] = x
			stri++
			space = false
		}
		x, err = s.tokenText()
	}
	if stri > 0 {
		l.token = string(str[:stri])
		l.tokenUpper = strings.ToUpper(l.token)
		l.length = stri
		l.value = zString
		debug.Printf("[%+v]", l.token)
		c <- l
	}
}
func classToInt(token string) (uint16, bool) {
	offset := 5
	if len(token) < offset+1 {
		return 0, false
	}
	class, err := strconv.ParseUint(token[offset:], 10, 16)
	if err != nil {
		return 0, false
	}
	return uint16(class), true
}