func (d *Dispenser) SyntaxErr(expected string) error {
	msg := fmt.Sprintf("%s:%d - Syntax error: Unexpected token '%s', expecting '%s'", d.File(), d.Line(), d.Val(), expected)
	return errors.New(msg)
}
SyntaxErr creates a generic syntax error which explains what was
found and what was expected.
package casketfile
import (
	"errors"
	"fmt"
	"io"
	"strings"
)
type Dispenser struct {
	filename string
	tokens   []Token
	cursor   int
	nesting  int
}
func NewDispenser(filename string, input io.Reader) Dispenser {
	tokens, _ := allTokens(input)  
	return Dispenser{
		filename: filename,
		tokens:   tokens,
		cursor:   -1,
	}
}
func NewDispenserTokens(filename string, tokens []Token) Dispenser {
	return Dispenser{
		filename: filename,
		tokens:   tokens,
		cursor:   -1,
	}
}
func (d *Dispenser) Next() bool {
	if d.cursor < len(d.tokens)-1 {
		d.cursor++
		return true
	}
	return false
}
func (d *Dispenser) NextArg() bool {
	if d.cursor < 0 {
		d.cursor++
		return true
	}
	if d.cursor >= len(d.tokens) {
		return false
	}
	if d.cursor < len(d.tokens)-1 &&
		d.tokens[d.cursor].File == d.tokens[d.cursor+1].File &&
		d.tokens[d.cursor].Line+d.numLineBreaks(d.cursor) == d.tokens[d.cursor+1].Line {
		d.cursor++
		return true
	}
	return false
}
func (d *Dispenser) NextLine() bool {
	if d.cursor < 0 {
		d.cursor++
		return true
	}
	if d.cursor >= len(d.tokens) {
		return false
	}
	if d.cursor < len(d.tokens)-1 &&
		(d.tokens[d.cursor].File != d.tokens[d.cursor+1].File ||
			d.tokens[d.cursor].Line+d.numLineBreaks(d.cursor) < d.tokens[d.cursor+1].Line) {
		d.cursor++
		return true
	}
	return false
}
func (d *Dispenser) NextBlock() bool {
	if d.nesting > 0 {
		d.Next()
		if d.Val() == "}" {
			d.nesting--
			return false
		}
		return true
	}
	if !d.NextArg() {  
		return false
	}
	if d.Val() != "{" {
		d.cursor--  
		return false
	}
	d.Next()
	if d.Val() == "}" {
		return false
	}
	d.nesting++
	return true
}
func (d *Dispenser) Val() string {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return ""
	}
	return d.tokens[d.cursor].Text
}
func (d *Dispenser) Line() int {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return 0
	}
	return d.tokens[d.cursor].Line
}
func (d *Dispenser) File() string {
	if d.cursor < 0 || d.cursor >= len(d.tokens) {
		return d.filename
	}
	if tokenFilename := d.tokens[d.cursor].File; tokenFilename != "" {
		return tokenFilename
	}
	return d.filename
}
func (d *Dispenser) Args(targets ...*string) bool {
	enough := true
	for i := 0; i < len(targets); i++ {
		if !d.NextArg() {
			enough = false
			break
		}
		*targets[i] = d.Val()
	}
	return enough
}
func (d *Dispenser) RemainingArgs() []string {
	var args []string
	for d.NextArg() {
		if d.Val() == "{" {
			d.cursor--
			break
		}
		args = append(args, d.Val())
	}
	return args
}
func (d *Dispenser) ArgErr() error {
	if d.Val() == "{" {
		return d.Err("Unexpected token '{', expecting argument")
	}
	return d.Errf("Wrong argument count or unexpected line ending after '%s'", d.Val())
}