func lexValue(lx *lexer) stateFn {
	r := lx.next()
	if isWhitespace(r) {
		return lexSkip(lx, lexValue)
	}
	switch {
	case r == arrayStart:
		lx.ignore()
		lx.emit(itemArrayStart)
		return lexArrayValue
	case r == mapStart:
		lx.ignore()
		lx.emit(itemMapStart)
		return lexMapKeyStart
	case r == sqStringStart:
		lx.ignore()  
		return lexQuotedString
	case r == dqStringStart:
		lx.ignore()  
		lx.stringStateFn = lexDubQuotedString
		return lexDubQuotedString
	case r == '-':
		return lexNegNumberStart
	case r == blockStart:
		lx.ignore()
		return lexBlock
	case unicode.IsDigit(r):
		lx.backup()  
		return lexNumberOrDateOrStringOrIPStart
	case r == '.':  
		return lx.errorf("Floats must start with a digit")
	case isNL(r):
		return lx.errorf("Expected value but found new line")
	}
	lx.backup()
	lx.stringStateFn = lexString
	return lexString
}
lexValue starts the consumption of a value anywhere a value is expected.
lexValue will ignore whitespace.
After a value is lexed, the last state on the next is popped and returned.
package conf
import (
	"encoding/hex"
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"
)
type itemType int
const (
	itemError itemType = iota
	itemNIL             
	itemEOF
	itemKey
	itemText
	itemString
	itemBool
	itemInteger
	itemFloat
	itemDatetime
	itemArrayStart
	itemArrayEnd
	itemMapStart
	itemMapEnd
	itemCommentStart
	itemVariable
	itemInclude
)
const (
	eof               = 0
	mapStart          = '{'
	mapEnd            = '}'
	keySepEqual       = '='
	keySepColon       = ':'
	arrayStart        = '['
	arrayEnd          = ']'
	arrayValTerm      = ','
	mapValTerm        = ','
	commentHashStart  = '#'
	commentSlashStart = '/'
	dqStringStart     = '"'
	dqStringEnd       = '"'
	sqStringStart     = '\''
	sqStringEnd       = '\''
	optValTerm        = ';'
	topOptStart       = '{'
	topOptValTerm     = ','
	topOptTerm        = '}'
	blockStart        = '('
	blockEnd          = ')'
)
type stateFn func(lx *lexer) stateFn
type lexer struct {
	input string
	start int
	pos   int
	width int
	line  int
	state stateFn
	items chan item
	stack []stateFn
	stringParts   []string
	stringStateFn stateFn
	lstart int
	ilstart int
}
type item struct {
	typ  itemType
	val  string
	line int
	pos  int
}
func (lx *lexer) nextItem() item {
	for {
		select {
		case item := <-lx.items:
			return item
		default:
			lx.state = lx.state(lx)
		}
	}
}
func lex(input string) *lexer {
	lx := &lexer{
		input:       input,
		state:       lexTop,
		line:        1,
		items:       make(chan item, 10),
		stack:       make([]stateFn, 0, 10),
		stringParts: []string{},
	}
	return lx
}
func (lx *lexer) push(state stateFn) {
	lx.stack = append(lx.stack, state)
}
func (lx *lexer) pop() stateFn {
	if len(lx.stack) == 0 {
		return lx.errorf("BUG in lexer: no states to pop.")
	}
	li := len(lx.stack) - 1
	last := lx.stack[li]
	lx.stack = lx.stack[0:li]
	return last
}
func (lx *lexer) emit(typ itemType) {
	val := strings.Join(lx.stringParts, "") + lx.input[lx.start:lx.pos]
	pos := lx.pos - lx.ilstart - len(val)
	lx.items <- item{typ, val, lx.line, pos}
	lx.start = lx.pos
	lx.ilstart = lx.lstart
}
func (lx *lexer) emitString() {
	var finalString string
	if len(lx.stringParts) > 0 {
		finalString = strings.Join(lx.stringParts, "") + lx.input[lx.start:lx.pos]
		lx.stringParts = []string{}
	} else {
		finalString = lx.input[lx.start:lx.pos]
	}
	pos := lx.pos - lx.ilstart - len(finalString)
	lx.items <- item{itemString, finalString, lx.line, pos}
	lx.start = lx.pos
	lx.ilstart = lx.lstart
}
func (lx *lexer) addCurrentStringPart(offset int) {
	lx.stringParts = append(lx.stringParts, lx.input[lx.start:lx.pos-offset])
	lx.start = lx.pos
}
func (lx *lexer) addStringPart(s string) stateFn {
	lx.stringParts = append(lx.stringParts, s)
	lx.start = lx.pos
	return lx.stringStateFn
}
func (lx *lexer) hasEscapedParts() bool {
	return len(lx.stringParts) > 0
}
func (lx *lexer) next() (r rune) {
	if lx.pos >= len(lx.input) {
		lx.width = 0
		return eof
	}
	if lx.input[lx.pos] == '\n' {
		lx.line++
		lx.lstart = lx.pos
	}
	r, lx.width = utf8.DecodeRuneInString(lx.input[lx.pos:])
	lx.pos += lx.width
	return r
}
func (lx *lexer) ignore() {
	lx.start = lx.pos
	lx.ilstart = lx.lstart
}
func (lx *lexer) backup() {
	lx.pos -= lx.width
	if lx.pos < len(lx.input) && lx.input[lx.pos] == '\n' {
		lx.line--
	}
}
func (lx *lexer) peek() rune {
	r := lx.next()
	lx.backup()
	return r
}
func (lx *lexer) errorf(format string, values ...interface{}) stateFn {
	for i, value := range values {
		if v, ok := value.(rune); ok {
			values[i] = escapeSpecial(v)
		}
	}
	pos := lx.pos - lx.lstart
	lx.items <- item{
		itemError,
		fmt.Sprintf(format, values...),
		lx.line,
		pos,
	}
	return nil
}
func lexTop(lx *lexer) stateFn {
	r := lx.next()
	if unicode.IsSpace(r) {
		return lexSkip(lx, lexTop)
	}
	switch r {
	case topOptStart:
		return lexSkip(lx, lexTop)
	case commentHashStart:
		lx.push(lexTop)
		return lexCommentStart
	case commentSlashStart:
		rn := lx.next()
		if rn == commentSlashStart {
			lx.push(lexTop)
			return lexCommentStart
		}
		lx.backup()
		fallthrough
	case eof:
		if lx.pos > lx.start {
			return lx.errorf("Unexpected EOF.")
		}
		lx.emit(itemEOF)
		return nil
	}
	lx.backup()
	lx.push(lexTopValueEnd)
	return lexKeyStart
}
func lexTopValueEnd(lx *lexer) stateFn {
	r := lx.next()
	switch {
	case r == commentHashStart:
		lx.push(lexTop)
		return lexCommentStart
	case r == commentSlashStart:
		rn := lx.next()
		if rn == commentSlashStart {
			lx.push(lexTop)
			return lexCommentStart
		}
		lx.backup()
		fallthrough
	case isWhitespace(r):
		return lexTopValueEnd
	case isNL(r) || r == eof || r == optValTerm || r == topOptValTerm || r == topOptTerm:
		lx.ignore()
		return lexTop
	}
	return lx.errorf("Expected a top-level value to end with a new line, "+
		"comment or EOF, but got '%v' instead.", r)
}
func lexKeyStart(lx *lexer) stateFn {
	r := lx.peek()
	switch {
	case isKeySeparator(r):
		return lx.errorf("Unexpected key separator '%v'", r)
	case unicode.IsSpace(r):
		lx.next()
		return lexSkip(lx, lexKeyStart)
	case r == dqStringStart:
		lx.next()
		return lexSkip(lx, lexDubQuotedKey)
	case r == sqStringStart:
		lx.next()
		return lexSkip(lx, lexQuotedKey)
	}
	lx.ignore()
	lx.next()
	return lexKey
}
func lexDubQuotedKey(lx *lexer) stateFn {
	r := lx.peek()
	if r == dqStringEnd {
		lx.emit(itemKey)
		lx.next()
		return lexSkip(lx, lexKeyEnd)
	} else if r == eof {
		if lx.pos > lx.start {
			return lx.errorf("Unexpected EOF.")
		}
		lx.emit(itemEOF)
		return nil
	}
	lx.next()
	return lexDubQuotedKey
}
func lexQuotedKey(lx *lexer) stateFn {
	r := lx.peek()
	if r == sqStringEnd {
		lx.emit(itemKey)
		lx.next()
		return lexSkip(lx, lexKeyEnd)
	} else if r == eof {
		if lx.pos > lx.start {
			return lx.errorf("Unexpected EOF.")
		}
		lx.emit(itemEOF)
		return nil
	}
	lx.next()
	return lexQuotedKey
}
func (lx *lexer) keyCheckKeyword(fallThrough, push stateFn) stateFn {
	key := strings.ToLower(lx.input[lx.start:lx.pos])
	switch key {
	case "include":
		lx.ignore()
		if push != nil {
			lx.push(push)
		}
		return lexIncludeStart
	}
	lx.emit(itemKey)
	return fallThrough
}
func lexIncludeStart(lx *lexer) stateFn {
	r := lx.next()
	if isWhitespace(r) {
		return lexSkip(lx, lexIncludeStart)
	}
	lx.backup()
	return lexInclude
}
func lexIncludeQuotedString(lx *lexer) stateFn {
	r := lx.next()
	switch {
	case r == sqStringEnd:
		lx.backup()
		lx.emit(itemInclude)
		lx.next()
		lx.ignore()
		return lx.pop()
	case r == eof:
		return lx.errorf("Unexpected EOF in quoted include")
	}
	return lexIncludeQuotedString
}
func lexIncludeDubQuotedString(lx *lexer) stateFn {
	r := lx.next()
	switch {
	case r == dqStringEnd:
		lx.backup()
		lx.emit(itemInclude)
		lx.next()
		lx.ignore()
		return lx.pop()
	case r == eof:
		return lx.errorf("Unexpected EOF in double quoted include")
	}
	return lexIncludeDubQuotedString
}
func lexIncludeString(lx *lexer) stateFn {
	r := lx.next()
	switch {
	case isNL(r) || r == eof || r == optValTerm || r == mapEnd || isWhitespace(r):
		lx.backup()
		lx.emit(itemInclude)
		return lx.pop()
	case r == sqStringEnd:
		lx.backup()
		lx.emit(itemInclude)
		lx.next()
		lx.ignore()
		return lx.pop()
	}
	return lexIncludeString
}
func lexInclude(lx *lexer) stateFn {
	r := lx.next()
	switch {
	case r == sqStringStart:
		lx.ignore()  
		return lexIncludeQuotedString
	case r == dqStringStart:
		lx.ignore()  
		return lexIncludeDubQuotedString
	case r == arrayStart:
		return lx.errorf("Expected include value but found start of an array")
	case r == mapStart:
		return lx.errorf("Expected include value but found start of a map")
	case r == blockStart:
		return lx.errorf("Expected include value but found start of a block")
	case unicode.IsDigit(r), r == '-':
		return lx.errorf("Expected include value but found start of a number")
	case r == '\\':
		return lx.errorf("Expected include value but found escape sequence")
	case isNL(r):
		return lx.errorf("Expected include value but found new line")
	}
	lx.backup()
	return lexIncludeString
}
func lexKey(lx *lexer) stateFn {
	r := lx.peek()
	if unicode.IsSpace(r) {
		return lx.keyCheckKeyword(lexKeyEnd, nil)
	} else if isKeySeparator(r) || r == eof {
		lx.emit(itemKey)
		return lexKeyEnd
	}
	lx.next()
	return lexKey
}
func lexKeyEnd(lx *lexer) stateFn {
	r := lx.next()
	switch {
	case unicode.IsSpace(r):
		return lexSkip(lx, lexKeyEnd)
	case isKeySeparator(r):
		return lexSkip(lx, lexValue)
	case r == eof:
		lx.emit(itemEOF)
		return nil
	}
	lx.backup()
	return lexValue
}