func (s *Scanner) init() (err error) {
	if s.b != nil {
		return nil
	}
	s.b, err = ioutil.ReadAll(s.r)
	return err
}
init slurps the reader on first scan.
package ego
import (
	"bytes"
	"fmt"
	"go/parser"
	"io"
	"io/ioutil"
	"unicode"
	"unicode/utf8"
)
type Scanner struct {
	r io.Reader
	b []byte
	i int
	pos Pos
}
func NewScanner(r io.Reader, path string) *Scanner {
	return &Scanner{
		r: r,
		pos: Pos{
			Path:   path,
			LineNo: 1,
		},
	}
}
func (s *Scanner) Scan() (Block, error) {
	if err := s.init(); err != nil {
		return nil, err
	}
	switch s.peek() {
	case '<':
		if s.peekComponentStartBlock() {
			return s.scanComponentStartBlock()
		} else if s.peekComponentEndBlock() {
			return s.scanComponentEndBlock()
		} else if s.peekAttrStartBlock() {
			return s.scanAttrStartBlock()
		} else if s.peekAttrEndBlock() {
			return s.scanAttrEndBlock()
		}
		if s.peekN(4) == "<%==" {
			return s.scanRawPrintBlock()
		} else if s.peekN(3) == "<%=" {
			return s.scanPrintBlock()
		} else if s.peekN(2) == "<%" {
			return s.scanCodeBlock()
		}
	case eof:
		return nil, io.EOF
	}
	return s.scanTextBlock()
}
func (s *Scanner) scanTextBlock() (*TextBlock, error) {
	buf := bytes.NewBufferString(s.readN(1))
	b := &TextBlock{Pos: s.pos}
	for {
		if ch := s.peek(); ch == eof || ch == '<' {
			break
		}
		buf.WriteRune(s.read())
	}
	b.Content = string(buf.Bytes())
	return b, nil
}
func (s *Scanner) scanCodeBlock() (*CodeBlock, error) {
	b := &CodeBlock{Pos: s.pos}
	assert(s.readN(2) == "<%")
	content, err := s.scanContent()
	if err != nil {
		return nil, err
	}
	b.Content = content
	return b, nil
}
func (s *Scanner) scanPrintBlock() (*PrintBlock, error) {
	b := &PrintBlock{Pos: s.pos}
	assert(s.readN(3) == "<%=")
	content, err := s.scanContent()
	if err != nil {
		return nil, err
	}
	b.Content = content
	return b, nil
}
func (s *Scanner) scanRawPrintBlock() (*RawPrintBlock, error) {
	b := &RawPrintBlock{Pos: s.pos}
	assert(s.readN(4) == "<%==")
	content, err := s.scanContent()
	if err != nil {
		return nil, err
	}
	b.Content = content
	return b, nil
}
func (s *Scanner) peekComponentStartBlock() bool {
	pos, i := s.pos, s.i
	defer func() { s.pos, s.i = pos, i }()
	if s.read() != '<' {
		return false
	} else if !s.peekIdent() {
		return false
	} else if s.read() != ':' {
		return false
	} else if s.read() == ':' {
		return false  
	}
	return true
}
func (s *Scanner) scanComponentStartBlock() (_ *ComponentStartBlock, err error) {
	b := &ComponentStartBlock{Pos: s.pos}
	assert(s.read() == '<')
	if b.Package, err = s.scanIdent(); err != nil {
		return nil, err
	} else if b.Package == "ego" {
		b.Package = ""
	}
	assert(s.read() == ':')
	if b.Name, err = s.scanIdent(); err != nil {
		return nil, err
	}
	for {
		s.skipWhitespace()
		if ch := s.peek(); ch == '>' {
			s.read()
			break
		} else if str := s.peekN(2); str == "/>" {
			s.readN(2)
			b.Closed = true
			break
		}
		if ch := s.peek(); unicode.IsUpper(ch) {
			field, err := s.scanField()
			if err != nil {
				return nil, err
			}
			b.Fields = append(b.Fields, field)
			continue
		}
		attr, err := s.scanAttr()
		if err != nil {
			return nil, err
		}
		b.Attrs = append(b.Attrs, attr)
	}
	return b, nil
}
func (s *Scanner) peekComponentEndBlock() bool {
	pos, i := s.pos, s.i
	defer func() { s.pos, s.i = pos, i }()
	if s.read() != '<' {
		return false
	} else if s.read() != '/' {
		return false
	} else if !s.peekIdent() {
		return false
	} else if s.read() != ':' {
		return false
	} else if s.read() == ':' {
		return false  
	}
	return true
}
func (s *Scanner) scanComponentEndBlock() (_ *ComponentEndBlock, err error) {
	b := &ComponentEndBlock{Pos: s.pos}
	assert(s.readN(2) == "</")
	if b.Package, err = s.scanIdent(); err != nil {
		return nil, err
	} else if b.Package == "ego" {
		b.Package = ""
	}
	assert(s.read() == ':')
	if b.Name, err = s.scanIdent(); err != nil {
		return nil, err
	}
	s.skipWhitespace()
	if ch := s.read(); ch != '>' {
		return nil, NewSyntaxError(s.pos, "Expected '>', found %s", runeString(ch))
	}
	return b, nil
}
func (s *Scanner) peekAttrStartBlock() bool {
	pos, i := s.pos, s.i
	defer func() { s.pos, s.i = pos, i }()
	if s.read() != '<' {
		return false
	} else if !s.peekIdent() {
		return false
	} else if s.read() != ':' {
		return false
	} else if s.read() != ':' {
		return false  
	}
	return true
}
func (s *Scanner) scanAttrStartBlock() (_ *AttrStartBlock, err error) {
	b := &AttrStartBlock{Pos: s.pos}
	assert(s.read() == '<')
	if b.Package, err = s.scanIdent(); err != nil {
		return nil, err
	} else if b.Package == "ego" {
		b.Package = ""
	}
	assert(s.read() == ':')
	assert(s.read() == ':')
	if b.Name, err = s.scanIdent(); err != nil {
		return nil, err
	}
	s.skipWhitespace()
	if ch := s.read(); ch != '>' {
		return nil, NewSyntaxError(s.pos, "Expected '>', found %s", runeString(ch))
	}
	return b, nil
}
func (s *Scanner) peekAttrEndBlock() bool {
	pos, i := s.pos, s.i
	defer func() { s.pos, s.i = pos, i }()
	if s.read() != '<' {
		return false
	} else if s.read() != '/' {
		return false
	} else if !s.peekIdent() {
		return false
	} else if s.read() != ':' {
		return false
	} else if s.read() != ':' {
		return false  
	}
	return true
}
func (s *Scanner) scanAttrEndBlock() (_ *AttrEndBlock, err error) {
	b := &AttrEndBlock{Pos: s.pos}
	assert(s.readN(2) == "</")
	if b.Package, err = s.scanIdent(); err != nil {
		return nil, err
	} else if b.Package == "ego" {
		b.Package = ""
	}
	assert(s.read() == ':')
	assert(s.read() == ':')
	if b.Name, err = s.scanIdent(); err != nil {
		return nil, err
	}
	s.skipWhitespace()
	if ch := s.read(); ch != '>' {
		return nil, NewSyntaxError(s.pos, "Expected '>', found %s", runeString(ch))
	}
	return b, nil
}
func (s *Scanner) scanContent() (string, error) {
	var buf bytes.Buffer
	for {
		ch := s.read()
		if ch == eof {
			return "", &SyntaxError{Message: "Expected close tag, found EOF", Pos: s.pos}
		} else if ch == '%' {
			ch := s.read()
			if ch == eof {
				return "", &SyntaxError{Message: "Expected close tag, found EOF", Pos: s.pos}
			} else if ch == '>' {
				break
			} else {
				buf.WriteRune('%')
				buf.WriteRune(ch)
			}
		} else {
			buf.WriteRune(ch)
		}
	}
	return string(buf.Bytes()), nil
}
func (s *Scanner) scanField() (*Field, error) {
	s.skipWhitespace()
	namePos := s.pos
	name, err := s.scanIdent()
	if err != nil {
		return nil, err
	}
	s.skipWhitespace()
	if ch := s.peek(); ch == '>' || isIdentStart(ch) {
		return &Field{Name: name, NamePos: namePos, Value: "true"}, nil
	} else if ch := s.peekN(2); ch == "/>" {
		return &Field{Name: name, NamePos: namePos, Value: "true"}, nil
	}
	if ch := s.read(); ch != '=' {
		return nil, NewSyntaxError(s.pos, "Expected '=', found %s", runeString(ch))
	}
	s.skipWhitespace()
	valuePos := s.pos
	value, err := s.scanExpr()
	if err != nil {
		return nil, err
	}
	return &Field{
		Name:     name,
		NamePos:  namePos,
		Value:    value,
		ValuePos: valuePos,
	}, nil
}
func (s *Scanner) scanAttr() (*Attr, error) {
	s.skipWhitespace()
	namePos := s.pos
	name, err := s.scanAttrName()
	if err != nil {
		return nil, err
	}
	s.skipWhitespace()
	if ch := s.peek(); ch == '>' || isIdentStart(ch) {
		return &Attr{Name: name, NamePos: namePos}, nil
	} else if ch := s.peekN(2); ch == "/>" {
		return &Attr{Name: name, NamePos: namePos}, nil
	}
	if ch := s.read(); ch != '=' {
		return nil, NewSyntaxError(s.pos, "Expected '=', found %s", runeString(ch))
	}
	s.skipWhitespace()
	valuePos := s.pos
	value, err := s.scanExpr()
	if err != nil {
		return nil, err
	}
	return &Attr{
		Name:     name,
		NamePos:  namePos,
		Value:    value,
		ValuePos: valuePos,
	}, nil
}
func (s *Scanner) peekIdent() bool {
	ident, _ := s.scanIdent()
	return ident != ""
}
func (s *Scanner) scanIdent() (string, error) {
	var buf bytes.Buffer
	ch := s.read()
	if !isIdentStart(ch) {
		return "", NewSyntaxError(s.pos, "Expected identifier, found %s", runeString(ch))
	}
	buf.WriteRune(ch)
	for ch := s.peek(); unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '_'; ch = s.peek() {
		buf.WriteRune(s.read())
	}
	return buf.String(), nil
}
func (s *Scanner) scanAttrName() (string, error) {
	var buf bytes.Buffer
	ch := s.read()
	if !isIdentStart(ch) {
		return "", NewSyntaxError(s.pos, "Expected identifier, found %s", runeString(ch))
	}
	buf.WriteRune(ch)
	for ch := s.peek(); unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '_' || ch == ':' || ch == '.' || ch == '-'; ch = s.peek() {
		buf.WriteRune(s.read())
	}
	return buf.String(), nil
}
func (s *Scanner) scanExpr() (string, error) {
	var buf bytes.Buffer
	pos := s.pos
	if ch := s.peek(); ch == eof {
		return "", NewSyntaxError(pos, "Expected Go expression, found EOF")
	}
	buf.WriteRune(s.read())
	for ch := s.peek(); ; ch = s.peek() {
		if isWhitespace(ch) && s.peekIgnoreWhitespace() == '{' {
			buf.WriteString(s.scanWhitespace())
			buf.WriteRune(s.read())
			continue
		}
		if isWhitespace(ch) || ch == eof || ch == '>' || s.peekN(2) == "/>" {
			if _, err := parser.ParseExpr(buf.String()); err != nil && ch == eof {
				return "", NewSyntaxError(pos, "Incomplete Go expression before EOF")
			} else if err == nil {
				break
			}
		}
		buf.WriteRune(s.read())
	}
	return buf.String(), nil
}
func (s *Scanner) scanWhitespace() string {
	var buf bytes.Buffer
	for ch := s.peek(); isWhitespace(ch); ch = s.peek() {
		buf.WriteRune(s.read())
	}
	return buf.String()
}