func (p *Parser) Block(t *token.Token) (ast.BlockStat, *token.Token) {
	var stats []ast.Stat
	var next ast.Stat
	for {
		switch t.Type {
		case token.KwReturn:
			ret, t := p.Return(t)
			return ast.NewBlockStat(stats, ret), t
		case token.KwEnd, token.KwElse, token.KwElseIf, token.KwUntil, token.EOF:
			return ast.NewBlockStat(stats, nil), t
		default:
			next, t = p.Stat(t)
			stats = append(stats, next)
		}
	}
}
Block parses a block whose starting token (e.g. "do") has already been
consumed. Returns the token that closes the block (e.g. "end"). So the caller
should check that this is the right kind of closing token.
package parsing
import (
	"errors"
	"fmt"
	"github.com/arnodel/golua/ops"
	"github.com/arnodel/golua/token"
	"github.com/arnodel/golua/ast"
)
type Parser struct {
	getToken func() *token.Token
}
type Error struct {
	Got      *token.Token
	Expected string
}
func (e Error) Error() string {
	expected := e.Expected
	if expected == "" {
		expected = "unexpected symbol"
	} else {
		expected = "expected " + expected
	}
	var tok string
	if e.Got.Type == token.EOF {
		tok = "<eof>"
	} else {
		tok = "'" + string(e.Got.Lit) + "'"
	}
	return fmt.Sprintf("%d:%d: %s near %s", e.Got.Line, e.Got.Column, expected, tok)
}
func ParseExp(getToken func() *token.Token) (exp ast.ExpNode, err error) {
	defer func() {
		if r := recover(); r != nil {
			exp = nil
			var ok bool
			err, ok = r.(error)
			if !ok {
				err = errors.New("Unknown error")
			}
		}
	}()
	parser := &Parser{getToken}
	var t *token.Token
	exp, t = parser.Exp(getToken())
	expectType(t, token.EOF, "<eof>")
	return
}
func ParseChunk(getToken func() *token.Token) (stat ast.BlockStat, err error) {
	defer func() {
		if r := recover(); r != nil {
			stat = ast.BlockStat{}
			var ok bool
			err, ok = r.(error)
			if !ok {
				err = errors.New("Unknown error")
			}
		}
	}()
	parser := &Parser{getToken}
	var t *token.Token
	stat, t = parser.Block(getToken())
	expectType(t, token.EOF, "<eof>")
	return
}
func (p *Parser) Scan() *token.Token {
	return p.getToken()
}
func (p *Parser) Stat(t *token.Token) (ast.Stat, *token.Token) {
	switch t.Type {
	case token.SgSemicolon:
		return ast.NewEmptyStat(t), p.Scan()
	case token.KwBreak:
		return ast.NewBreakStat(t), p.Scan()
	case token.KwGoto:
		dest := p.Scan()
		expectIdent(dest)
		return ast.NewGotoStat(t, ast.NewName(dest)), p.Scan()
	case token.KwDo:
		stat, closer := p.Block(p.Scan())
		expectType(closer, token.KwEnd, "'end'")
		return stat, p.Scan()
	case token.KwWhile:
		cond, doTok := p.Exp(p.Scan())
		expectType(doTok, token.KwDo, "'do'")
		body, endTok := p.Block(p.Scan())
		expectType(endTok, token.KwEnd, "'end'")
		return ast.NewWhileStat(t, endTok, cond, body), p.Scan()
	case token.KwRepeat:
		body, untilTok := p.Block(p.Scan())
		expectType(untilTok, token.KwUntil, "'until'")
		cond, next := p.Exp(p.Scan())
		return ast.NewRepeatStat(t, body, cond), next
	case token.KwIf:
		return p.If(t)
	case token.KwFor:
		return p.For(t)
	case token.KwFunction:
		return p.FunctionStat(t)
	case token.KwLocal:
		return p.Local(t)
	case token.SgDoubleColon:
		name, t := p.Name(p.Scan())
		expectType(t, token.SgDoubleColon, "'::'")
		return ast.NewLabelStat(name), p.Scan()
	default:
		var exp ast.ExpNode
		exp, t = p.PrefixExp(t)
		switch e := exp.(type) {
		case ast.Stat:
			return e, t
		case ast.Var:
			vars := []ast.Var{e}
			var pexp ast.ExpNode
			for t.Type == token.SgComma {
				pexp, t = p.PrefixExp(p.Scan())
				if v, ok := pexp.(ast.Var); ok {
					vars = append(vars, v)
				} else {
					tokenError(t, "expected variable")
				}
			}
			expectType(t, token.SgAssign, "'='")
			exps, t := p.ExpList(p.Scan())
			return ast.NewAssignStat(vars, exps), t
		default:
			tokenError(t, "")
		}
	}
	return nil, nil
}
func (p *Parser) If(t *token.Token) (ast.IfStat, *token.Token) {
	cond, thenTok := p.Exp(p.Scan())
	expectType(thenTok, token.KwThen, "'then'")
	thenBlock, endTok := p.Block(p.Scan())
	ifStat := ast.NewIfStat(t, cond, thenBlock)
	for {
		switch endTok.Type {
		case token.KwElseIf:
			cond, thenTok = p.Exp(p.Scan())
			expectType(thenTok, token.KwThen, "'then'")
			thenBlock, endTok = p.Block(p.Scan())
			ifStat = ifStat.AddElseIf(cond, thenBlock)
		case token.KwEnd:
			return ifStat, p.Scan()
		case token.KwElse:
			elseBlock, elseTok := p.Block(p.Scan())
			expectType(elseTok, token.KwEnd, "'end'")
			ifStat = ifStat.WithElse(endTok, elseBlock)
			return ifStat, p.Scan()
		default:
			tokenError(t, "'elseif' or 'end' or 'else'")
		}
	}
}
func (p *Parser) For(t *token.Token) (ast.Stat, *token.Token) {
	name, nextTok := p.Name(p.Scan())
	if nextTok.Type == token.SgAssign {
		params := make([]ast.ExpNode, 3)
		params[0], nextTok = p.Exp(p.Scan())
		expectType(nextTok, token.SgComma, "','")
		params[1], nextTok = p.Exp(p.Scan())
		if nextTok.Type == token.SgComma {
			params[2], nextTok = p.Exp(p.Scan())
		} else {
			params[2] = ast.NewInt(1)
		}
		expectType(nextTok, token.KwDo, "'do'")
		body, endTok := p.Block(p.Scan())
		expectType(endTok, token.KwEnd, "'end'")
		forStat := ast.NewForStat(t, endTok, name, params, body)
		return forStat, p.Scan()
	}
	names := []ast.Name{name}
	for nextTok.Type == token.SgComma {
		name, nextTok = p.Name(p.Scan())
		names = append(names, name)
	}
	expected := "'in'"
	if len(names) == 1 {
		expected = "'=' or 'in'"
	}
	expectType(nextTok, token.KwIn, expected)
	exp, nextTok := p.Exp(p.Scan())
	params := []ast.ExpNode{exp}
	for nextTok.Type == token.SgComma {
		exp, nextTok = p.Exp(p.Scan())
		params = append(params, exp)
	}
	expectType(nextTok, token.KwDo, "'do'")
	body, endTok := p.Block(p.Scan())
	expectType(endTok, token.KwEnd, "'end'")
	forInStat := ast.NewForInStat(t, endTok, names, params, body)
	return forInStat, p.Scan()
}
func (p *Parser) Local(t *token.Token) (ast.Stat, *token.Token) {
	t = p.Scan()
	if t.Type == token.KwFunction {
		name, t := p.Name(p.Scan())
		fx, t := p.FunctionDef(t)
		return ast.NewLocalFunctionStat(name, fx), t
	}
	name, t := p.Name(t)
	names := []ast.Name{name}
	for t.Type == token.SgComma {
		name, t = p.Name(p.Scan())
		names = append(names, name)
	}
	var values []ast.ExpNode
	if t.Type == token.SgAssign {
		values, t = p.ExpList(p.Scan())
	}
	return ast.NewLocalStat(names, values), t
}
func (p *Parser) FunctionStat(t *token.Token) (ast.Stat, *token.Token) {
	name, t := p.Name(p.Scan())
	var v ast.Var = name
	var method ast.Name
	for t.Type == token.SgDot {
		name, t = p.Name(p.Scan())
		v = ast.NewIndexExp(v, name.AstString())
	}
	if t.Type == token.SgColon {
		method, t = p.Name(p.Scan())
	}
	fx, t := p.FunctionDef(t)
	return ast.NewFunctionStat(v, method, fx), t
}