func (p *Parser) parseShowSeriesCardinalityStatement(exact bool) (Statement, error) {
	var err error
	stmt := &ShowSeriesCardinalityStatement{Exact: exact}
	if tok, _, _ := p.ScanIgnoreWhitespace(); tok == ON {
		if stmt.Database, err = p.ParseIdent(); err != nil {
			return nil, err
		}
	} else {
		p.Unscan()
	}
	if tok, _, _ := p.ScanIgnoreWhitespace(); tok == FROM {
		if stmt.Sources, err = p.parseSources(false); err != nil {
			return nil, err
		}
	} else {
		p.Unscan()
	}
	if stmt.Condition, err = p.parseCondition(); err != nil {
		return nil, err
	}
	if stmt.Dimensions, err = p.parseDimensions(); err != nil {
		return nil, err
	}
	if stmt.Limit, err = p.ParseOptionalTokenAndInt(LIMIT); err != nil {
		return nil, err
	} else if stmt.Offset, err = p.ParseOptionalTokenAndInt(OFFSET); err != nil {
		return nil, err
	}
	return stmt, nil
}
This function assumes the "SHOW SERIES EXACT CARDINALITY" or the
"SHOW SERIES CARDINALITY" tokens have already been consumed.
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
}
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)
}
func (p *Parser) parseSelectStatement(tr targetRequirement) (*SelectStatement, error) {
	stmt := &SelectStatement{}
	var err error
	if stmt.Fields, err = p.parseFields(); err != nil {
		return nil, err
	}
	if stmt.Target, err = p.parseTarget(tr); err != nil {
		return nil, err
	}
	if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != FROM {
		return nil, newParseError(tokstr(tok, lit), []string{"FROM"}, pos)
	}
	if stmt.Sources, err = p.parseSources(true); err != nil {
		return nil, err
	}
	if stmt.Condition, err = p.parseCondition(); err != nil {
		return nil, err
	}
	if stmt.Dimensions, err = p.parseDimensions(); err != nil {
		return nil, err
	}
	if stmt.Fill, stmt.FillValue, err = p.parseFill(); err != nil {
		return nil, err
	}
	if stmt.SortFields, err = p.parseOrderBy(); err != nil {
		return nil, err
	}
	if stmt.Limit, err = p.ParseOptionalTokenAndInt(LIMIT); err != nil {
		return nil, err
	}
	if stmt.Offset, err = p.ParseOptionalTokenAndInt(OFFSET); err != nil {
		return nil, err
	}
	if stmt.SLimit, err = p.ParseOptionalTokenAndInt(SLIMIT); err != nil {
		return nil, err
	}
	if stmt.SOffset, err = p.ParseOptionalTokenAndInt(SOFFSET); err != nil {
		return nil, err
	}
	if stmt.Location, err = p.parseLocation(); err != nil {
		return nil, err
	}
	stmt.IsRawQuery = true
	WalkFunc(stmt.Fields, func(n Node) {
		if _, ok := n.(*Call); ok {
			stmt.IsRawQuery = false
		}
	})
	return stmt, nil
}
type targetRequirement int
const (
	targetRequired targetRequirement = iota
	targetNotRequired
	targetSubquery
)
func (p *Parser) parseTarget(tr targetRequirement) (*Target, error) {
	if tok, pos, lit := p.ScanIgnoreWhitespace(); tok != INTO {
		if tr == targetRequired {
			return nil, newParseError(tokstr(tok, lit), []string{"INTO"}, pos)
		}
		p.Unscan()
		return nil, nil
	}
	idents, err := p.parseSegmentedIdents()
	if err != nil {
		return nil, err
	}
	if len(idents) < 3 {
		if ch := p.peekRune(); ch == ':' {
			if err := p.parseTokens([]Token{COLON, MEASUREMENT}); err != nil {
				return nil, err
			}
			idents = append(idents, "")
		}
	}
	t := &Target{Measurement: &Measurement{IsTarget: true}}
	switch len(idents) {
	case 1:
		t.Measurement.Name = idents[0]
	case 2:
		t.Measurement.RetentionPolicy = idents[0]
		t.Measurement.Name = idents[1]
	case 3:
		t.Measurement.Database = idents[0]
		t.Measurement.RetentionPolicy = idents[1]
		t.Measurement.Name = idents[2]
	}
	return t, nil
}
func (p *Parser) parseDeleteStatement() (Statement, error) {
	stmt := &DeleteSeriesStatement{}
	var err error
	tok, pos, lit := p.ScanIgnoreWhitespace()
	if tok == FROM {
		if stmt.Sources, err = p.parseSources(false); err != nil {
			return nil, err
		}
		var err error
		WalkFunc(stmt.Sources, func(n Node) {
			if t, ok := n.(*Measurement); ok {
				if t.Database != "" {
					err = &ParseError{Message: "database not supported"}
				}
				if t.RetentionPolicy != "" {
					err = &ParseError{Message: "retention policy not supported"}
				}
			}
		})
		if err != nil {
			return nil, err
		}
	} else {
		p.Unscan()
	}
	if stmt.Condition, err = p.parseCondition(); err != nil {
		return nil, err
	}
	if stmt.Condition == nil && stmt.Sources == nil {
		return nil, newParseError(tokstr(tok, lit), []string{"FROM", "WHERE"}, pos)
	}
	return stmt, nil
}
func (p *Parser) parseShowSeriesStatement() (Statement, error) {
	var exactCardinality bool
	if tok, _, _ := p.ScanIgnoreWhitespace(); tok == EXACT {
		exactCardinality = true
	} else {
		p.Unscan()
	}
	if tok, _, _ := p.ScanIgnoreWhitespace(); tok == CARDINALITY {
		return p.parseShowSeriesCardinalityStatement(exactCardinality)
	}
	p.Unscan()
	stmt := &ShowSeriesStatement{}
	var err error
	if tok, _, _ := p.ScanIgnoreWhitespace(); tok == ON {
		stmt.Database, err = p.ParseIdent()
		if err != nil {
			return nil, err
		}
	} else {
		p.Unscan()
	}
	if tok, _, _ := p.ScanIgnoreWhitespace(); tok == FROM {
		if stmt.Sources, err = p.parseSources(false); err != nil {
			return nil, err
		}
	} else {
		p.Unscan()
	}
	if stmt.Condition, err = p.parseCondition(); err != nil {
		return nil, err
	}
	if stmt.SortFields, err = p.parseOrderBy(); err != nil {
		return nil, err
	}
	if stmt.Limit, err = p.ParseOptionalTokenAndInt(LIMIT); err != nil {
		return nil, err
	}
	if stmt.Offset, err = p.ParseOptionalTokenAndInt(OFFSET); err != nil {
		return nil, err
	}
	return stmt, nil
}