func lexNumber(l *lexer) stateFn {
	if !l.scanNumber() {
		return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
	}
	l.emit(itemNumber)
	return lexInsideScript
}
lexNumber scans a number: decimal, octal, hex or float.  This
isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
and "089" - but when it's wrong the input is invalid and the parser (via
strconv) will notice.
package base
import (
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"
)
type item struct {
	typ itemType
	val string
}
func (i item) String() string {
	switch {
	case i.typ == itemEOF:
		return "EOF"
	case i.typ == itemError:
		return i.val
	case len(i.val) > 30:
		return fmt.Sprintf("%.30q...", i.val)
	}
	return fmt.Sprintf("%q", i.val)
}
type itemType int
const (
	itemError    itemType = iota  
	itemDatabase                  
	itemBool                      
	itemEOF
	itemEqual              
	itemPlusEqual          
	itemMinusEqual         
	itemColon              
	itemDot                
	itemSemiColon          
	itemComma              
	itemSendTo             
	itemLeftBrace          
	itemRightBrace         
	itemLeftParenthesis    
	itemRightParenthesis   
	itemLeftBracket        
	itemRightBracket       
	itemEqualTo            
	itemNotEqualTo         
	itemGreaterThan        
	itemGreaterThanEquals  
	itemLesserThan         
	itemLesserThanEquals   
	itemIdentifier         
	itemNumber             
	itemString             
	itemPath               
	itemOption             
	itemKeyword  
	itemNull
)
var itemName = map[itemType]string{
	itemError:             "error",
	itemBool:              "bool",
	itemDatabase:          "database",
	itemEqual:             "=",
	itemPlusEqual:         "+=",
	itemMinusEqual:        "-=",
	itemColon:             ":",
	itemDot:               ".",
	itemSemiColon:         ";",
	itemComma:             ",",
	itemSendTo:            ">>",
	itemLeftBrace:         "{",
	itemRightBrace:        "}",
	itemLeftParenthesis:   "(",
	itemRightParenthesis:  ")",
	itemLeftBracket:       "[",
	itemRightBracket:      "]",
	itemEqualTo:           "==",
	itemNotEqualTo:        "!=",
	itemGreaterThan:       ">",
	itemGreaterThanEquals: ">=",
	itemLesserThan:        "<",
	itemLesserThanEquals:  "<=",
	itemEOF:               "EOF",
	itemIdentifier:        "identifier",
	itemNumber:            "number",
	itemString:            "string",
	itemPath:              "path",
	itemOption:            "--",
	itemNull:              "null",
}
func (i itemType) String() string {
	s := itemName[i]
	if s == "" {
		return fmt.Sprintf("item%d", int(i))
	}
	return s
}
const eof = -1
type stateFn func(*lexer) stateFn
type lexer struct {
	input string     
	state stateFn    
	pos   int        
	start int        
	width int        
	items chan item  
}
func (l *lexer) next() (r rune) {
	if l.pos >= len(l.input) {
		l.width = 0
		return eof
	}
	r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
	l.pos += l.width
	return r
}
func (l *lexer) peek() rune {
	r := l.next()
	l.backup()
	return r
}
func (l *lexer) backup() {
	l.pos -= l.width
}
func (l *lexer) emit(t itemType) {
	l.items <- item{t, l.input[l.start:l.pos]}
	l.start = l.pos
}
func (l *lexer) ignore() {
	l.start = l.pos
}
func (l *lexer) accept(valid string) bool {
	if strings.IndexRune(valid, l.next()) >= 0 {
		return true
	}
	l.backup()
	return false
}
func (l *lexer) acceptRun(valid string) {
	for strings.IndexRune(valid, l.next()) >= 0 {
	}
	l.backup()
}
func (l *lexer) lineNumber() int {
	return 1 + strings.Count(l.input[:l.pos], "\n")
}
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
	l.items <- item{itemError, fmt.Sprintf(format, args...)}
	return nil
}
func (l *lexer) nextItem() item {
	for {
		select {
		case item := <-l.items:
			return item
		default:
			l.state = l.state(l)
		}
	}
	panic("not reached")
}
func lex(input string) *lexer {
	l := &lexer{
		input: input,
		state: lexInsideScript,
		items: make(chan item, 2),  
	}
	return l
}
const (
	leftComment  = "/*"
	rightComment = "*/"
)
func lexComment(l *lexer) stateFn {
	l.pos += len(leftComment)
	i := strings.Index(l.input[l.pos:], rightComment)
	if i < 0 {
		return l.errorf("unclosed comment")
	}
	l.pos += i + len(rightComment)
	l.ignore()
	return lexInsideScript
}
func lexDatabase(l *lexer) stateFn {
	letters := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	digits := "0123456789"
	specials := "_"
	if !l.accept(letters) {
		return l.errorf("database name must start with a letter")
	}
	l.acceptRun(letters + digits + specials)
	l.emit(itemDatabase)
	return lexInsideScript
}
func lexInsideScript(l *lexer) stateFn {
	switch r := l.next(); {
	case r == eof:
		break
	case isSpace(r):
		l.ignore()
		return lexInsideScript
	case r == '@':
		l.ignore()
		return lexDatabase
	case r == '/':
		if l.peek() == '*' {
			return lexComment
		}
		return lexPath
	case r == '<':
		if l.next() == '=' {
			l.emit(itemLesserThanEquals)
			return lexInsideScript
		}
		l.backup()
		l.emit(itemLesserThan)
		return lexInsideScript
	case r == '>':
		switch nxt := l.next(); {
		case nxt == '=':
			l.emit(itemGreaterThanEquals)
			break
		case nxt == '>':
			l.emit(itemSendTo)
			break
		default:
			l.backup()
			l.emit(itemGreaterThan)
		}
		return lexInsideScript
	case r == '!':
		if l.next() == '=' {
			l.emit(itemNotEqualTo)
			return lexInsideScript
		}
		return l.errorf("expected !=")
	case r == '=':
		if l.peek() == '=' {
			l.next()
			l.emit(itemEqualTo)
			return lexInsideScript
		}
		l.emit(itemEqual)
		return lexInsideScript
	case r == ';':
		l.emit(itemSemiColon)
		return lexInsideScript
	case r == '.':
		l.emit(itemDot)
		return lexInsideScript
	case r == ':':
		l.emit(itemColon)
		return lexInsideScript
	case r == ',':
		l.emit(itemComma)
		return lexInsideScript
	case r == '(':
		l.emit(itemLeftParenthesis)
		return lexInsideScript
	case r == '[':
		l.emit(itemLeftBracket)
		return lexInsideScript
	case r == '{':
		l.emit(itemLeftBrace)
		return lexInsideScript
	case r == ')':
		l.emit(itemRightParenthesis)
		return lexInsideScript
	case r == ']':
		l.emit(itemRightBracket)
		return lexInsideScript
	case r == '}':
		l.emit(itemRightBrace)
		return lexInsideScript
	case r == '"':
		return lexDoubleQuote
	case r == '\'':
		return lexSingleQuote
	case r == '+':
		if l.peek() == '=' {
			l.next()
			l.emit(itemPlusEqual)
			return lexInsideScript
		}
		l.backup()
		return lexNumber
	case r == '-':
		pk := l.peek()
		if pk == '=' {
			l.next()
			l.emit(itemMinusEqual)
			return lexInsideScript
		} else if pk == '-' {
			l.next()
			l.emit(itemOption)
			return lexInsideScript
		}
		l.backup()
		return lexNumber
	case ('0' <= r && r <= '9'):
		l.backup()
		return lexNumber
	case isAlphaNumeric(r):
		l.backup()
		return lexIdentifier
	default:
		return l.errorf("unrecognized character in script: %#U", r)
	}
	l.emit(itemEOF)
	return nil
}
func lexIdentifier(l *lexer) stateFn {
Loop:
	for {
		switch r := l.next(); {
		case isAlphaNumeric(r):
			break
		default:
			l.backup()
			word := l.input[l.start:l.pos]
			switch id := strings.ToLower(word); {
			case id == "null":
				l.emit(itemNull)
			case id == "true", id == "false":
				l.emit(itemBool)
			default:
				l.emit(itemIdentifier)
			}
			break Loop
		}
	}
	return lexInsideScript
}
func lexDoubleQuote(l *lexer) stateFn {
Loop:
	for {
		switch l.next() {
		case '\\':
			if r := l.next(); r != eof && r != '\n' {
				break
			}
			fallthrough
		case eof, '\n':
			return l.errorf("unterminated quoted string")
		case '"':
			break Loop
		}
	}
	l.emit(itemString)
	return lexInsideScript
}
func lexSingleQuote(l *lexer) stateFn {
Loop:
	for {
		switch l.next() {
		case '\\':
			if r := l.next(); r != eof && r != '\n' {
				break
			}
			fallthrough
		case eof, '\n':
			return l.errorf("unterminated quoted string")
		case '\'':
			break Loop
		}
	}
	l.emit(itemString)
	return lexInsideScript
}