func (l *Lexer) readIdent() (string, error) {
	b := []rune{l.curRune()}
	for l.nextRune() {
		if unicode.IsSpace(l.curRune()) || strings.ContainsRune("@#,{}=\"(", l.curRune()) {
			return string(b), l.Err()
		} else {
			b = append(b, l.curRune())
		}
	}
	return "", l.Err()
}
readIdent reads an identifier which is a continugous string on non-space
characters that are not @#,{}="( which are the special characters used by
bibtex
package lexer
import (
	"bufio"
	"io"
	"strings"
	"unicode"
)
type TokenType string
type Token struct {
	Type    TokenType
	Literal string
	lineno  int
	colno   int
}
const (
	ILLEGAL TokenType = "ILLEGAL"
	EOF               = "EOF"
	IDENT             = "IDENT"
	STRING            = "STRING"
	AT                = "@"
	COMMA             = ","
	LBRACE            = "{"
	RBRACE            = "}"
	HASH              = "#"
	EQUALS            = "="
)
var EOFToken = &Token{Type: EOF}
func (t *Token) Position() (int, int) {
	return t.lineno, t.colno
}
type Lexer struct {
	stream *bufio.Reader
	ch     rune
	err    error
	lineno int
	colno  int
}
func New(f io.Reader) *Lexer {
	l := Lexer{
		stream: bufio.NewReader(f),
		ch:     0,
		err:    nil,
		lineno: 1,
		colno:  1,
	}
	l.nextRune()
	return &l
}
func (l *Lexer) nextRune() bool {
	ch, _, err := l.stream.ReadRune()
	if err != nil {
		l.err = err
		return false
	}
	l.ch = ch
	l.colno++
	if l.ch == '\n' {
		l.lineno++
		l.colno = 1
	}
	return true
}
func (l *Lexer) Position() (int, int) {
	return l.lineno, l.colno
}
func (l *Lexer) curRune() rune {
	return l.ch
}
func (l *Lexer) Err() error {
	return l.err
}
func (l *Lexer) skipWhitespace() error {
	first := true
	for first || l.nextRune() {
		if !unicode.IsSpace(l.curRune()) {
			return l.Err()
		}
		first = false
	}
	return l.Err()
}
func (l *Lexer) SkipToNewLine() error {
    for l.curRune() != '\n' {
        l.nextRune()
    }
    return l.Err()
}
func (l *Lexer) readQuoteString() (string, error) {
	escape := false
	b := make([]rune, 0)
	for l.nextRune() {
		if l.curRune() == '"' && !escape {
			l.nextRune()
			return string(b), l.Err()
		} else {
			b = append(b, l.curRune())
		}
		escape = !escape && l.curRune() == '\\'
	}
	return "", l.Err()
}