func (p *Parser) parsePrivilege() (Privilege, error) {
	tok, pos, lit := p.ScanIgnoreWhitespace()
	switch tok {
	case READ:
		return ReadPrivilege, nil
	case WRITE:
		return WritePrivilege, nil
	case ALL:
		tok, pos, lit = p.ScanIgnoreWhitespace()
		if tok != PRIVILEGES {
			p.Unscan()
		}
		return AllPrivileges, nil
	}
	return 0, newParseError(tokstr(tok, lit), []string{"READ", "WRITE", "ALL [PRIVILEGES]"}, pos)
}
parsePrivilege parses a string and returns a Privilege.
package influxql
import (
	"errors"
	"fmt"
	"io"
	"math"
	"regexp"
	"strconv"
	"strings"
	"time"
)
const (
	DateFormat = "2006-01-02"
	DateTimeFormat = "2006-01-02 15:04:05.999999"
)
type Parser struct {
	s      *bufScanner
	params map[string]Value
}
func NewParser(r io.Reader) *Parser {
	return &Parser{s: newBufScanner(r)}
}
func (p *Parser) SetParams(params map[string]interface{}) {
	p.params = make(map[string]Value, len(params))
	for name, param := range params {
		p.params[name] = BindValue(param)
	}
}
func ParseQuery(s string) (*Query, error) { return NewParser(strings.NewReader(s)).ParseQuery() }
func ParseStatement(s string) (Statement, error) {
	return NewParser(strings.NewReader(s)).ParseStatement()
}
func MustParseStatement(s string) Statement {
	stmt, err := ParseStatement(s)
	if err != nil {
		panic(err.Error())
	}
	return stmt
}
func ParseExpr(s string) (Expr, error) { return NewParser(strings.NewReader(s)).ParseExpr() }
func MustParseExpr(s string) Expr {
	expr, err := ParseExpr(s)
	if err != nil {
		panic(err.Error())
	}
	return expr
}
func (p *Parser) ParseQuery() (*Query, error) {
	var statements Statements
	semi := true
	for {
		if tok, pos, lit := p.ScanIgnoreWhitespace(); tok == EOF {
			return &Query{Statements: statements}, nil
		} else if tok == SEMICOLON {
			semi = true
		} else {
			if !semi {
				return nil, newParseError(tokstr(tok, lit), []string{";"}, pos)
			}
			p.Unscan()
			s, err := p.ParseStatement()
			if err != nil {
				return nil, err
			}
			statements = append(statements, s)
			semi = false
		}
	}
}
func (p *Parser) ParseStatement() (Statement, error) {
	return Language.Parse(p)
}
func (p *Parser) parseSetPasswordUserStatement() (*SetPasswordUserStatement, error) {
	stmt := &SetPasswordUserStatement{}
	ident, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.Name = ident
	if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != EQ {
		return nil, newParseError(tokstr(tok, lit), []string{"="}, pos)
	}
	if ident, err = p.parseString(); err != nil {
		return nil, err
	}
	stmt.Password = ident
	return stmt, nil
}
func (p *Parser) parseKillQueryStatement() (*KillQueryStatement, error) {
	qid, err := p.ParseUInt64()
	if err != nil {
		return nil, err
	}
	var host string
	if tok, _, _ := p.ScanIgnoreWhitespace(); tok == ON {
		host, err = p.ParseIdent()
		if err != nil {
			return nil, err
		}
	} else {
		p.Unscan()
	}
	return &KillQueryStatement{QueryID: qid, Host: host}, nil
}
func (p *Parser) parseCreateSubscriptionStatement() (*CreateSubscriptionStatement, error) {
	stmt := &CreateSubscriptionStatement{}
	ident, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.Name = ident
	if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != ON {
		return nil, newParseError(tokstr(tok, lit), []string{"ON"}, pos)
	}
	if ident, err = p.ParseIdent(); err != nil {
		return nil, err
	}
	stmt.Database = ident
	if tok, pos, lit := p.Scan(); tok != DOT {
		return nil, newParseError(tokstr(tok, lit), []string{"."}, pos)
	}
	if ident, err = p.ParseIdent(); err != nil {
		return nil, err
	}
	stmt.RetentionPolicy = ident
	if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != DESTINATIONS {
		return nil, newParseError(tokstr(tok, lit), []string{"DESTINATIONS"}, pos)
	}
	if tok, pos, lit := p.ScanIgnoreWhitespace(); tok == ALL || tok == ANY {
		stmt.Mode = tokens[tok]
	} else {
		return nil, newParseError(tokstr(tok, lit), []string{"ALL", "ANY"}, pos)
	}
	var destinations []string
	if destinations, err = p.parseStringList(); err != nil {
		return nil, err
	}
	stmt.Destinations = destinations
	return stmt, nil
}
func (p *Parser) parseCreateRetentionPolicyStatement() (*CreateRetentionPolicyStatement, error) {
	stmt := &CreateRetentionPolicyStatement{}
	ident, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.Name = ident
	if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != ON {
		return nil, newParseError(tokstr(tok, lit), []string{"ON"}, pos)
	}
	ident, err = p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.Database = ident
	if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != DURATION {
		return nil, newParseError(tokstr(tok, lit), []string{"DURATION"}, pos)
	}
	d, err := p.ParseDuration()
	if err != nil {
		return nil, err
	}
	stmt.Duration = d
	if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != REPLICATION {
		return nil, newParseError(tokstr(tok, lit), []string{"REPLICATION"}, pos)
	}
	n, err := p.ParseInt(1, math.MaxInt32)
	if err != nil {
		return nil, err
	}
	stmt.Replication = n
	if tok, _, _ := p.ScanIgnoreWhitespace(); tok == SHARD {
		if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != DURATION {
			return nil, newParseError(tokstr(tok, lit), []string{"DURATION"}, pos)
		}
		tok, pos, _ := p.ScanIgnoreWhitespace()
		if tok == INF {
			return nil, &ParseError{
				Message: "invalid duration INF for shard duration",
				Pos:     pos,
			}
		}
		p.Unscan()
		d, err := p.ParseDuration()
		if err != nil {
			return nil, err
		}
		stmt.ShardGroupDuration = d
	} else {
		p.Unscan()
	}
	if tok, _, _ := p.ScanIgnoreWhitespace(); tok == DEFAULT {
		stmt.Default = true
	} else {
		p.Unscan()
	}
	return stmt, nil
}
func (p *Parser) parseAlterRetentionPolicyStatement() (*AlterRetentionPolicyStatement, error) {
	stmt := &AlterRetentionPolicyStatement{}
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok == DEFAULT {
		stmt.Name = "default"
	} else if tok == IDENT {
		stmt.Name = lit
	} else {
		return nil, newParseError(tokstr(tok, lit), []string{"identifier"}, pos)
	}
	if tok, pos, lit = p.ScanIgnoreWhitespace(); tok != ON {
		return nil, newParseError(tokstr(tok, lit), []string{"ON"}, pos)
	}
	ident, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.Database = ident
	found := make(map[Token]struct{})
Loop:
	for {
		tok, pos, lit := p.ScanIgnoreWhitespace()
		if _, ok := found[tok]; ok {
			return nil, &ParseError{
				Message: fmt.Sprintf("found duplicate %s option", tok),
				Pos:     pos,
			}
		}
		switch tok {
		case DURATION:
			d, err := p.ParseDuration()
			if err != nil {
				return nil, err
			}
			stmt.Duration = &d
		case REPLICATION:
			n, err := p.ParseInt(1, math.MaxInt32)
			if err != nil {
				return nil, err
			}
			stmt.Replication = &n
		case SHARD:
			tok, pos, lit := p.ScanIgnoreWhitespace()
			if tok == DURATION {
				tok, pos, _ := p.ScanIgnoreWhitespace()
				if tok == INF {
					return nil, &ParseError{
						Message: "invalid duration INF for shard duration",
						Pos:     pos,
					}
				}
				p.Unscan()
				d, err := p.ParseDuration()
				if err != nil {
					return nil, err
				}
				stmt.ShardGroupDuration = &d
			} else {
				return nil, newParseError(tokstr(tok, lit), []string{"DURATION"}, pos)
			}
		case DEFAULT:
			stmt.Default = true
		default:
			if len(found) == 0 {
				return nil, newParseError(tokstr(tok, lit), []string{"DURATION", "REPLICATION", "SHARD", "DEFAULT"}, pos)
			}
			p.Unscan()
			break Loop
		}
		found[tok] = struct{}{}
	}
	return stmt, nil
}
func (p *Parser) ParseInt(min, max int) (int, error) {
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok != INTEGER {
		return 0, newParseError(tokstr(tok, lit), []string{"integer"}, pos)
	}
	n, err := strconv.Atoi(lit)
	if err != nil {
		return 0, &ParseError{Message: err.Error(), Pos: pos}
	} else if min > n || n > max {
		return 0, &ParseError{
			Message: fmt.Sprintf("invalid value %d: must be %d <= n <= %d", n, min, max),
			Pos:     pos,
		}
	}
	return n, nil
}
func (p *Parser) ParseUInt64() (uint64, error) {
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok != INTEGER {
		return 0, newParseError(tokstr(tok, lit), []string{"integer"}, pos)
	}
	n, err := strconv.ParseUint(lit, 10, 64)
	if err != nil {
		return 0, &ParseError{Message: err.Error(), Pos: pos}
	}
	return uint64(n), nil
}
func (p *Parser) ParseDuration() (time.Duration, error) {
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok != DURATIONVAL && tok != INF {
		return 0, newParseError(tokstr(tok, lit), []string{"duration"}, pos)
	}
	if tok == INF {
		return 0, nil
	}
	d, err := ParseDuration(lit)
	if err != nil {
		return 0, &ParseError{Message: err.Error(), Pos: pos}
	}
	return d, nil
}
func (p *Parser) ParseIdent() (string, error) {
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok != IDENT {
		return "", newParseError(tokstr(tok, lit), []string{"identifier"}, pos)
	}
	return lit, nil
}
func (p *Parser) ParseIdentList() ([]string, error) {
	ident, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	idents := []string{ident}
	for {
		if tok, _, _ := p.ScanIgnoreWhitespace(); tok != COMMA {
			p.Unscan()
			return idents, nil
		}
		if ident, err = p.ParseIdent(); err != nil {
			return nil, err
		}
		idents = append(idents, ident)
	}
}
func (p *Parser) parseSegmentedIdents() ([]string, error) {
	ident, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	idents := []string{ident}
	for {
		if tok, _, _ := p.Scan(); tok != DOT {
			p.Unscan()
			break
		}
		if ch := p.peekRune(); ch == '/' {
			break
		} else if ch == ':' {
			break
		} else if ch == '.' {
			idents = append(idents, "")
			continue
		}
		if ident, err = p.ParseIdent(); err != nil {
			return nil, err
		}
		idents = append(idents, ident)
	}
	if len(idents) > 3 {
		msg := fmt.Sprintf("too many segments in %s", QuoteIdent(idents...))
		return nil, &ParseError{Message: msg}
	}
	return idents, nil
}
func (p *Parser) parseString() (string, error) {
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok != STRING {
		return "", newParseError(tokstr(tok, lit), []string{"string"}, pos)
	}
	return lit, nil
}
func (p *Parser) parseStringList() ([]string, error) {
	str, err := p.parseString()
	if err != nil {
		return nil, err
	}
	strs := []string{str}
	for {
		if tok, _, _ := p.ScanIgnoreWhitespace(); tok != COMMA {
			p.Unscan()
			return strs, nil
		}
		if str, err = p.parseString(); err != nil {
			return nil, err
		}
		strs = append(strs, str)
	}
}
func (p *Parser) parseRevokeStatement() (Statement, error) {
	priv, err := p.parsePrivilege()
	if err != nil {
		return nil, err
	}
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok == ON {
		stmt, err := p.parseRevokeOnStatement()
		if err != nil {
			return nil, err
		}
		stmt.Privilege = priv
		return stmt, nil
	} else if tok == FROM {
		if priv != AllPrivileges {
			return nil, newParseError(tokstr(tok, lit), []string{"ON"}, pos)
		}
		return p.parseRevokeAdminStatement()
	}
	if priv == AllPrivileges {
		return nil, newParseError(tokstr(tok, lit), []string{"ON", "FROM"}, pos)
	}
	return nil, newParseError(tokstr(tok, lit), []string{"ON"}, pos)
}
func (p *Parser) parseRevokeOnStatement() (*RevokeStatement, error) {
	stmt := &RevokeStatement{}
	lit, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.On = lit
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok != FROM {
		return nil, newParseError(tokstr(tok, lit), []string{"FROM"}, pos)
	}
	lit, err = p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.User = lit
	return stmt, nil
}
func (p *Parser) parseRevokeAdminStatement() (*RevokeAdminStatement, error) {
	stmt := &RevokeAdminStatement{}
	lit, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.User = lit
	return stmt, nil
}
func (p *Parser) parseGrantStatement() (Statement, error) {
	priv, err := p.parsePrivilege()
	if err != nil {
		return nil, err
	}
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok == ON {
		stmt, err := p.parseGrantOnStatement()
		if err != nil {
			return nil, err
		}
		stmt.Privilege = priv
		return stmt, nil
	} else if tok == TO {
		if priv != AllPrivileges {
			return nil, newParseError(tokstr(tok, lit), []string{"ON"}, pos)
		}
		return p.parseGrantAdminStatement()
	}
	if priv == AllPrivileges {
		return nil, newParseError(tokstr(tok, lit), []string{"ON", "TO"}, pos)
	}
	return nil, newParseError(tokstr(tok, lit), []string{"ON"}, pos)
}
func (p *Parser) parseGrantOnStatement() (*GrantStatement, error) {
	stmt := &GrantStatement{}
	lit, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.On = lit
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok != TO {
		return nil, newParseError(tokstr(tok, lit), []string{"TO"}, pos)
	}
	lit, err = p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.User = lit
	return stmt, nil
}
func (p *Parser) parseGrantAdminStatement() (*GrantAdminStatement, error) {
	stmt := &GrantAdminStatement{}
	lit, err := p.ParseIdent()
	if err != nil {
		return nil, err
	}
	stmt.User = lit
	return stmt, nil
}