func parseSource(src []byte, script bool) (tree *ast.Tree, err error) {
	tree = ast.NewTree("", nil, ast.FormatText)
	var p = &parsing{
		isScript:  script,
		ancestors: []ast.Node{tree},
	}
	if script {
		p.lex = scanScript(src)
	} else {
		p.lex = scanProgram(src)
	}
	defer func() {
		p.lex.Stop()
		if r := recover(); r != nil {
			if e, ok := r.(*SyntaxError); ok {
				tree = nil
				err = e
			} else {
				panic(r)
			}
		}
	}()
	tok := p.next()
	if tok.typ == tokenShebangLine {
		tok = p.next()
	}
	for tok.typ != tokenEOF {
		tok = p.parse(tok, tokenEOF)
	}
	if len(p.ancestors) == 1 {
		if !script && len(tree.Nodes) == 0 {
			panic(syntaxError(tok.pos, "expected 'package', found 'EOF'"))
		}
	} else {
		switch p.ancestors[1].(type) {
		case *ast.Package:
		case *ast.Label:
			return nil, syntaxError(tok.pos, "missing statement after label")
		default:
			if len(p.ancestors) > 2 {
				return nil, syntaxError(tok.pos, "unexpected EOF, expecting }")
			}
		}
	}
	return tree, nil
}
parseSource parses a program or a script and returns its tree.
script reports whether it is a script.
package compiler
import (
	"errors"
	"fmt"
	"strings"
	"unicode/utf8"
	"github.com/open2b/scriggo/ast"
	"github.com/open2b/scriggo/ast/astutil"
)
type SyntaxError struct {
	path string
	pos  ast.Position
	msg  string
}
func (e *SyntaxError) Error() string {
	return fmt.Sprintf("%s:%s: syntax error: %s", e.path, e.pos, e.msg)
}
func (e *SyntaxError) Message() string {
	return e.msg
}
func (e *SyntaxError) Path() string {
	return e.path
}
func (e *SyntaxError) Position() ast.Position {
	return e.pos
}
func syntaxError(pos *ast.Position, format string, a ...interface{}) *SyntaxError {
	return &SyntaxError{"", *pos, fmt.Sprintf(format, a...)}
}
type CycleError struct {
	path string
	pos  ast.Position
	msg  string
}
func (e *CycleError) Error() string {
	return e.msg
}
func (e *CycleError) Path() string {
	return e.path
}
func (e *CycleError) Position() ast.Position {
	return e.pos
}
func (e *CycleError) Message() string {
	return e.msg
}
func containsOnlySpaces(bytes []byte) bool {
	for _, b := range bytes {
		if b != ' ' && b != '\t' && b != '\n' && b != '\r' {
			return false
		}
	}
	return true
}
func firstNonSpacePosition(tok token) *ast.Position {
	pos := *(tok.pos)
	for i, b := range tok.txt {
		switch b {
		case ' ', '\t', '\r':
			pos.Column++
		case '\n':
			pos.Line++
			pos.Column = 1
		default:
			_, n := utf8.DecodeRune(tok.txt[i:])
			pos.Start += i
			pos.End = pos.Start + n
			return &pos
		}
	}
	return nil
}
type parsing struct {
	lex *lexer
	format ast.Format
	isScript bool
	imported bool
	hasExtend bool
	cutSpacesToken bool
	ancestors []ast.Node
	unexpanded []ast.Node
}
func (p *parsing) addToAncestors(node ast.Node) {
	p.ancestors = append(p.ancestors, node)
}
func (p *parsing) removeLastAncestor() {
	p.ancestors = p.ancestors[0 : len(p.ancestors)-1]
}
func (p *parsing) parent() ast.Node {
	return p.ancestors[len(p.ancestors)-1]
}
func (p *parsing) inFunction() bool {
	for i := len(p.ancestors) - 1; i > 0; i-- {
		if n, ok := p.ancestors[i].(*ast.Func); ok {
			return !n.Type.Macro
		}
	}
	return false
}
func (p *parsing) next() token {
	tok, ok := <-p.lex.Tokens()
	if !ok {
		if p.lex.err == nil {
			panic("next called after EOF")
		}
		panic(p.lex.err)
	}
	return tok
}