text: package stressql
  
  import (
  	"bufio"
  	"bytes"
  	"io"
  	"log"
  	"os"
  	"strings"
  
  	"github.com/influxdata/influxdb/influxql"
  	"github.com/influxdata/influxdb/stress/v2/statement"
  	stressql "github.com/influxdata/influxdb/stress/v2/stressql/statement"
  )
  
  // Token represents a lexical token.
  type Token int
  
  // These are the lexical tokens used by the file parser
  const (
  	ILLEGAL Token = iota
  	EOF
  	STATEMENT
  	BREAK
  )
  
  var eof = rune(0)
  
  func check(e error) {
  	if e != nil {
  		log.Fatal(e)
  	}
  }
  
  func isNewline(r rune) bool {
  	return r == '\n'
  }
  
  // Scanner scans the file and tokenizes the raw text
  type Scanner struct {
  	r *bufio.Reader
  }
  
  // NewScanner returns a Scanner
  func NewScanner(r io.Reader) *Scanner {
  	return &Scanner{r: bufio.NewReader(r)}
  }
  
  func (s *Scanner) read() rune {
  	ch, _, err := s.r.ReadRune()
  	if err != nil {
  		return eof
  	}
  	return ch
  }
  
  func (s *Scanner) unread() { _ = s.r.UnreadRune() }
  
  func (s *Scanner) peek() rune {
  	ch := s.read()
  	s.unread()
  	return ch
  }
  
  // Scan moves the Scanner forward one character
  func (s *Scanner) Scan() (tok Token, lit string) {
  	ch := s.read()
  
  	if isNewline(ch) {
  		s.unread()
  		return s.scanNewlines()
  	} else if ch == eof {
  		return EOF, ""
  	} else {
  		s.unread()
  		return s.scanStatements()
  	}
  	// golint marks as unreachable code
  	// return ILLEGAL, string(ch)
  }
  
  func (s *Scanner) scanNewlines() (tok Token, lit string) {
  	var buf bytes.Buffer
  	buf.WriteRune(s.read())
  
  	for {
  		if ch := s.read(); ch == eof {
  			break
  		} else if !isNewline(ch) {
  			s.unread()
  			break
  		} else {
  			buf.WriteRune(ch)
  		}
  	}
  
  	return BREAK, buf.String()
  }
  
  func (s *Scanner) scanStatements() (tok Token, lit string) {
  	var buf bytes.Buffer
  	buf.WriteRune(s.read())
  
  	for {
  		if ch := s.read(); ch == eof {
  			break
  		} else if isNewline(ch) && isNewline(s.peek()) {
  			s.unread()
  			break
  		} else if isNewline(ch) {
  			s.unread()
  			buf.WriteRune(ch)
  		} else {
  			buf.WriteRune(ch)
  		}
  	}
  
  	return STATEMENT, buf.String()
  }
  
  // ParseStatements takes a configFile and returns a slice of Statements
  func ParseStatements(file string) ([]statement.Statement, error) {
  	seq := []statement.Statement{}
  
  	f, err := os.Open(file)
  	check(err)
  
  	s := NewScanner(f)
  
  	for {
  		t, l := s.Scan()
  
  		if t == EOF {
  			break
  		}
  		_, err := influxql.ParseStatement(l)
  		if err == nil {
  
  			seq = append(seq, &statement.InfluxqlStatement{Query: l, StatementID: stressql.RandStr(10)})
  		} else if t == BREAK {
  			continue
  		} else {
  			f := strings.NewReader(l)
  			p := stressql.NewParser(f)
  			s, err := p.Parse()
  			if err != nil {
  				return nil, err
  			}
  			seq = append(seq, s)
  
  		}
  	}
  
  	f.Close()
  
  	return seq, nil
  
  }
  