func (zp *ZoneParser) Next() (RR, bool) {
	if zp.parseErr != nil {
		return nil, false
	}
	if zp.sub != nil {
		return zp.subNext()
	}
	st := zExpectOwnerDir  
	h := &zp.h
	for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() {
		if l.err {
			return zp.setParseError(l.token, l)
		}
		switch st {
		case zExpectOwnerDir:
			if zp.defttl != nil {
				h.Ttl = zp.defttl.ttl
			}
			h.Class = ClassINET
			switch l.value {
			case zNewline:
				st = zExpectOwnerDir
			case zOwner:
				name, ok := toAbsoluteName(l.token, zp.origin)
				if !ok {
					return zp.setParseError("bad owner name", l)
				}
				h.Name = name
				st = zExpectOwnerBl
			case zDirTTL:
				st = zExpectDirTTLBl
			case zDirOrigin:
				st = zExpectDirOriginBl
			case zDirInclude:
				st = zExpectDirIncludeBl
			case zDirGenerate:
				st = zExpectDirGenerateBl
			case zRrtpe:
				h.Rrtype = l.torc
				st = zExpectRdata
			case zClass:
				h.Class = l.torc
				st = zExpectAnyNoClassBl
			case zBlank:
			case zString:
				ttl, ok := stringToTTL(l.token)
				if !ok {
					return zp.setParseError("not a TTL", l)
				}
				h.Ttl = ttl
				if zp.defttl == nil || !zp.defttl.isByDirective {
					zp.defttl = &ttlState{ttl, false}
				}
				st = zExpectAnyNoTTLBl
			default:
				return zp.setParseError("syntax error at beginning", l)
			}
		case zExpectDirIncludeBl:
			if l.value != zBlank {
				return zp.setParseError("no blank after $INCLUDE-directive", l)
			}
			st = zExpectDirInclude
		case zExpectDirInclude:
			if l.value != zString {
				return zp.setParseError("expecting $INCLUDE value, not this...", l)
			}
			neworigin := zp.origin  
			switch l, _ := zp.c.Next(); l.value {
			case zBlank:
				l, _ := zp.c.Next()
				if l.value == zString {
					name, ok := toAbsoluteName(l.token, zp.origin)
					if !ok {
						return zp.setParseError("bad origin name", l)
					}
					neworigin = name
				}
			case zNewline, zEOF:
			default:
				return zp.setParseError("garbage after $INCLUDE", l)
			}
			if !zp.includeAllowed {
				return zp.setParseError("$INCLUDE directive not allowed", l)
			}
			if zp.includeDepth >= maxIncludeDepth {
				return zp.setParseError("too deeply nested $INCLUDE", l)
			}
			includePath := l.token
			if !filepath.IsAbs(includePath) {
				includePath = filepath.Join(filepath.Dir(zp.file), includePath)
			}
			r1, e1 := os.Open(includePath)
			if e1 != nil {
				var as string
				if !filepath.IsAbs(l.token) {
					as = fmt.Sprintf(" as `%s'", includePath)
				}
				msg := fmt.Sprintf("failed to open `%s'%s: %v", l.token, as, e1)
				return zp.setParseError(msg, l)
			}
			zp.sub = NewZoneParser(r1, neworigin, includePath)
			zp.sub.defttl, zp.sub.includeDepth, zp.sub.osFile = zp.defttl, zp.includeDepth+1, r1
			zp.sub.SetIncludeAllowed(true)
			return zp.subNext()
		case zExpectDirTTLBl:
			if l.value != zBlank {
				return zp.setParseError("no blank after $TTL-directive", l)
			}
			st = zExpectDirTTL
		case zExpectDirTTL:
			if l.value != zString {
				return zp.setParseError("expecting $TTL value, not this...", l)
			}
			if err := slurpRemainder(zp.c); err != nil {
				return zp.setParseError(err.err, err.lex)
			}
			ttl, ok := stringToTTL(l.token)
			if !ok {
				return zp.setParseError("expecting $TTL value, not this...", l)
			}
			zp.defttl = &ttlState{ttl, true}
			st = zExpectOwnerDir
		case zExpectDirOriginBl:
			if l.value != zBlank {
				return zp.setParseError("no blank after $ORIGIN-directive", l)
			}
			st = zExpectDirOrigin
		case zExpectDirOrigin:
			if l.value != zString {
				return zp.setParseError("expecting $ORIGIN value, not this...", l)
			}
			if err := slurpRemainder(zp.c); err != nil {
				return zp.setParseError(err.err, err.lex)
			}
			name, ok := toAbsoluteName(l.token, zp.origin)
			if !ok {
				return zp.setParseError("bad origin name", l)
			}
			zp.origin = name
			st = zExpectOwnerDir
		case zExpectDirGenerateBl:
			if l.value != zBlank {
				return zp.setParseError("no blank after $GENERATE-directive", l)
			}
			st = zExpectDirGenerate
		case zExpectDirGenerate:
			if l.value != zString {
				return zp.setParseError("expecting $GENERATE value, not this...", l)
			}
			return zp.generate(l)
		case zExpectOwnerBl:
			if l.value != zBlank {
				return zp.setParseError("no blank after owner", l)
			}
			st = zExpectAny
		case zExpectAny:
			switch l.value {
			case zRrtpe:
				if zp.defttl == nil {
					return zp.setParseError("missing TTL with no previous value", l)
				}
				h.Rrtype = l.torc
				st = zExpectRdata
			case zClass:
				h.Class = l.torc
				st = zExpectAnyNoClassBl
			case zString:
				ttl, ok := stringToTTL(l.token)
				if !ok {
					return zp.setParseError("not a TTL", l)
				}
				h.Ttl = ttl
				if zp.defttl == nil || !zp.defttl.isByDirective {
					zp.defttl = &ttlState{ttl, false}
				}
				st = zExpectAnyNoTTLBl
			default:
				return zp.setParseError("expecting RR type, TTL or class, not this...", l)
			}
		case zExpectAnyNoClassBl:
			if l.value != zBlank {
				return zp.setParseError("no blank before class", l)
			}
			st = zExpectAnyNoClass
		case zExpectAnyNoTTLBl:
			if l.value != zBlank {
				return zp.setParseError("no blank before TTL", l)
			}
			st = zExpectAnyNoTTL
		case zExpectAnyNoTTL:
			switch l.value {
			case zClass:
				h.Class = l.torc
				st = zExpectRrtypeBl
			case zRrtpe:
				h.Rrtype = l.torc
				st = zExpectRdata
			default:
				return zp.setParseError("expecting RR type or class, not this...", l)
			}
		case zExpectAnyNoClass:
			switch l.value {
			case zString:
				ttl, ok := stringToTTL(l.token)
				if !ok {
					return zp.setParseError("not a TTL", l)
				}
				h.Ttl = ttl
				if zp.defttl == nil || !zp.defttl.isByDirective {
					zp.defttl = &ttlState{ttl, false}
				}
				st = zExpectRrtypeBl
			case zRrtpe:
				h.Rrtype = l.torc
				st = zExpectRdata
			default:
				return zp.setParseError("expecting RR type or TTL, not this...", l)
			}
		case zExpectRrtypeBl:
			if l.value != zBlank {
				return zp.setParseError("no blank before RR type", l)
			}
			st = zExpectRrtype
		case zExpectRrtype:
			if l.value != zRrtpe {
				return zp.setParseError("unknown RR type", l)
			}
			h.Rrtype = l.torc
			st = zExpectRdata
		case zExpectRdata:
			var rr RR
			if newFn, ok := TypeToRR[h.Rrtype]; ok && canParseAsRR(h.Rrtype) {
				rr = newFn()
				*rr.Header() = *h
			} else {
				rr = &RFC3597{Hdr: *h}
			}
			_, isPrivate := rr.(*PrivateRR)
			if !isPrivate && zp.c.Peek().token == "" {
				if err := slurpRemainder(zp.c); err != nil {
					return zp.setParseError(err.err, err.lex)
				}
				return rr, true
			} else if l.value == zNewline {
				return zp.setParseError("unexpected newline", l)
			}
			if err := rr.parse(zp.c, zp.origin); err != nil {
				if err.lex == (lex{}) {
					return zp.setParseError(err.err, l)
				}
				return zp.setParseError(err.err, err.lex)
			}
			return rr, true
		}
	}
	return nil, false
}
Next advances the parser to the next RR in the zonefile and
returns the (RR, true). It will return (nil, false) when the
parsing stops, either by reaching the end of the input or an
error. After Next returns (nil, false), the Err method will return
any error that occurred during parsing.
package dns
import (
	"bufio"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)
const maxTok = 2048  
const maxIncludeDepth = 7
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  
	err    bool    
	value  uint8   
	torc   uint16  
	line   int     
	column int     
}
type Token struct {
	RR
	Error *ParseError
	Comment string
}
type ttlState struct {
	ttl           uint32  
	isByDirective bool    
}
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(r io.Reader, file string) (RR, error) {
	zp := NewZoneParser(r, ".", file)
	zp.SetDefaultTTL(defaultTtl)
	zp.SetIncludeAllowed(true)
	rr, _ := zp.Next()
	return rr, zp.Err()
}
func ParseZone(r io.Reader, origin, file string) chan *Token {
	t := make(chan *Token, 10000)
	go parseZone(r, origin, file, t)
	return t
}
func parseZone(r io.Reader, origin, file string, t chan *Token) {
	defer close(t)
	zp := NewZoneParser(r, origin, file)
	zp.SetIncludeAllowed(true)
	for rr, ok := zp.Next(); ok; rr, ok = zp.Next() {
		t <- &Token{RR: rr, Comment: zp.Comment()}
	}
	if err := zp.Err(); err != nil {
		pe, ok := err.(*ParseError)
		if !ok {
			pe = &ParseError{file: file, err: err.Error()}
		}
		t <- &Token{Error: pe}
	}
}
type ZoneParser struct {
	c *zlexer
	parseErr *ParseError
	origin string
	file   string
	defttl *ttlState
	h RR_Header
	sub    *ZoneParser
	osFile *os.File
	includeDepth uint8
	includeAllowed bool
}
func NewZoneParser(r io.Reader, origin, file string) *ZoneParser {
	var pe *ParseError
	if origin != "" {
		origin = Fqdn(origin)
		if _, ok := IsDomainName(origin); !ok {
			pe = &ParseError{file, "bad initial origin name", lex{}}
		}
	}
	return &ZoneParser{
		c: newZLexer(r),
		parseErr: pe,
		origin: origin,
		file:   file,
	}
}
func (zp *ZoneParser) SetDefaultTTL(ttl uint32) {
	zp.defttl = &ttlState{ttl, false}
}
func (zp *ZoneParser) SetIncludeAllowed(v bool) {
	zp.includeAllowed = v
}
func (zp *ZoneParser) Err() error {
	if zp.parseErr != nil {
		return zp.parseErr
	}
	if zp.sub != nil {
		if err := zp.sub.Err(); err != nil {
			return err
		}
	}
	return zp.c.Err()
}
func (zp *ZoneParser) setParseError(err string, l lex) (RR, bool) {
	zp.parseErr = &ParseError{zp.file, err, l}
	return nil, false
}
func (zp *ZoneParser) Comment() string {
	if zp.parseErr != nil {
		return ""
	}
	if zp.sub != nil {
		return zp.sub.Comment()
	}
	return zp.c.Comment()
}
func (zp *ZoneParser) subNext() (RR, bool) {
	if rr, ok := zp.sub.Next(); ok {
		return rr, true
	}
	if zp.sub.osFile != nil {
		zp.sub.osFile.Close()
		zp.sub.osFile = nil
	}
	if zp.sub.Err() != nil {
		return nil, false
	}
	zp.sub = nil
	return zp.Next()
}