func (p *Parser) readCSV() (results []string, err error) {
	// skip preceding whitespace
	p.skipWhiteSpace()

	const (
		stateBeforeParens              = 0
		stateWord                      = 1
		stateWhitespaceAfterOpenParens = 2
		stateWhitespaceAfterComma      = 3
		stateWhitespaceAfterWord       = 4
	)

	var word []rune
	var ch rune
	var state int

	for {
		if p.done() {
			results = nil
			err = p.parseError("csv; expects close parenthesis")
			// err = ErrInvalidSelector
			return
		}

		ch = p.current()

		switch state {
		case stateBeforeParens:
			if ch == OpenParens {
				state = stateWhitespaceAfterOpenParens
				p.advance()
				continue
			}

			// not open parens, bail
			err = p.parseError("csv; expects open parenthesis")
			results = nil
			return

		case stateWord:

			if ch == Comma {
				if len(word) > 0 {
					results = append(results, string(word))
					word = nil
				}

				// the symbol is the comma
				state = stateWhitespaceAfterComma
				p.advance()
				continue
			}

			if ch == CloseParens {
				if len(word) > 0 {
					results = append(results, string(word))
				}
				p.advance()
				return
			}

			if p.isWhitespace(ch) {
				if len(word) > 0 {
					results = append(results, string(word))
					word = nil
				}

				state = stateWhitespaceAfterWord
				p.advance()
				continue
			}

			if !p.isValidValue(ch) {
				err = p.parseError("csv; word contains invalid characters")
				results = nil
				return
			}

			word = append(word, ch)
			p.advance()
			continue

		case stateWhitespaceAfterOpenParens, stateWhitespaceAfterComma:
			if p.isWhitespace(ch) {
				p.advance()
				continue
			}
			if isAlpha(ch) {
				state = stateWord
				continue
			}
			if ch == Comma {
				p.advance()
				state = stateWhitespaceAfterComma
				continue
			}
			if ch == CloseParens {
				p.advance()
				return // exit reading the csv
			}

			if state == stateWhitespaceAfterOpenParens {
				err = p.parseError("csv; invalid characters after '('")
				return
			}
			err = p.parseError("csv; invalid characters after ','")
			return

		case stateWhitespaceAfterWord:

			if ch == CloseParens {
				if len(word) > 0 {
					results = append(results, string(word))
				}
				p.advance()
				return
			}

			if p.isWhitespace(ch) {
				p.advance()
				continue
			}

			if ch == Comma {
				state = stateWhitespaceAfterComma
				p.advance()
				continue
			}

			err = p.parseError("csv; consecutive whitespace separated words without a comma")
			results = nil
			return
		}
	}
}
// readCSV reads an array of strings in csv form.
// it expects to start just before the first `(` and
// will read until just past the closing `)`
readCSV reads an array of strings in csv form.
it expects to start just before the first `(` and
will read until just past the closing `)`
// readCSV reads an array of strings in csv form . // it expects to start just before the first ` ( ` and // will read until just past the closing ` ) `
func (p *Parser) readCSV() (results []string, err error) {
	p.skipWhiteSpace()
	const (
		stateBeforeParens              = 0
		stateWord                      = 1
		stateWhitespaceAfterOpenParens = 2
		stateWhitespaceAfterComma      = 3
		stateWhitespaceAfterWord       = 4
	)
	var word []rune
	var ch rune
	var state int
	for {
		if p.done() {
			results = nil
			err = p.parseError("csv; expects close parenthesis")
			return
		}
		ch = p.current()
		switch state {
		case stateBeforeParens:
			if ch == OpenParens {
				state = stateWhitespaceAfterOpenParens
				p.advance()
				continue
			}
			err = p.parseError("csv; expects open parenthesis")
			results = nil
			return
		case stateWord:
			if ch == Comma {
				if len(word) > 0 {
					results = append(results, string(word))
					word = nil
				}
				state = stateWhitespaceAfterComma
				p.advance()
				continue
			}
			if ch == CloseParens {
				if len(word) > 0 {
					results = append(results, string(word))
				}
				p.advance()
				return
			}
			if p.isWhitespace(ch) {
				if len(word) > 0 {
					results = append(results, string(word))
					word = nil
				}
				state = stateWhitespaceAfterWord
				p.advance()
				continue
			}
			if !p.isValidValue(ch) {
				err = p.parseError("csv; word contains invalid characters")
				results = nil
				return
			}
			word = append(word, ch)
			p.advance()
			continue
		case stateWhitespaceAfterOpenParens, stateWhitespaceAfterComma:
			if p.isWhitespace(ch) {
				p.advance()
				continue
			}
			if isAlpha(ch) {
				state = stateWord
				continue
			}
			if ch == Comma {
				p.advance()
				state = stateWhitespaceAfterComma
				continue
			}
			if ch == CloseParens {
				p.advance()
				return 
			}
			if state == stateWhitespaceAfterOpenParens {
				err = p.parseError("csv; invalid characters after '('")
				return
			}
			err = p.parseError("csv; invalid characters after ','")
			return
		case stateWhitespaceAfterWord:
			if ch == CloseParens {
				if len(word) > 0 {
					results = append(results, string(word))
				}
				p.advance()
				return
			}
			if p.isWhitespace(ch) {
				p.advance()
				continue
			}
			if ch == Comma {
				state = stateWhitespaceAfterComma
				p.advance()
				continue
			}
			err = p.parseError("csv; consecutive whitespace separated words without a comma")
			results = nil
			return
		}
	}
}
func ( p * Parser ) readCSV ( ) ( results [ ] string , err error ) { p . skipWhiteSpace ( ) const ( stateBeforeParens = 0 stateWord = 1 stateWhitespaceAfterOpenParens = 2 stateWhitespaceAfterComma = 3 stateWhitespaceAfterWord = 4 ) var word [ ] rune var ch rune var state int for { if p . done ( ) { results = nil err = p . parseError ( " " ) return } ch = p . current ( ) switch state { case stateBeforeParens : if ch == OpenParens { state = stateWhitespaceAfterOpenParens p . advance ( ) continue } err = p . parseError ( " " ) results = nil return case stateWord : if ch == Comma { if len ( word ) > 0 { results = append ( results , string ( word ) ) word = nil } state = stateWhitespaceAfterComma p . advance ( ) continue } if ch == CloseParens { if len ( word ) > 0 { results = append ( results , string ( word ) ) } p . advance ( ) return } if p . isWhitespace ( ch ) { if len ( word ) > 0 { results = append ( results , string ( word ) ) word = nil } state = stateWhitespaceAfterWord p . advance ( ) continue } if ! p . isValidValue ( ch ) { err = p . parseError ( " " ) results = nil return } word = append ( word , ch ) p . advance ( ) continue case stateWhitespaceAfterOpenParens , stateWhitespaceAfterComma : if p . isWhitespace ( ch ) { p . advance ( ) continue } if isAlpha ( ch ) { state = stateWord continue } if ch == Comma { p . advance ( ) state = stateWhitespaceAfterComma continue } if ch == CloseParens { p . advance ( ) return } if state == stateWhitespaceAfterOpenParens { err = p . parseError ( " " ) return } err = p . parseError ( " " ) return case stateWhitespaceAfterWord : if ch == CloseParens { if len ( word ) > 0 { results = append ( results , string ( word ) ) } p . advance ( ) return } if p . isWhitespace ( ch ) { p . advance ( ) continue } if ch == Comma { state = stateWhitespaceAfterComma p . advance ( ) continue } err = p . parseError ( " " ) results = nil return } } }
readCSV reads an array of strings in csv form.
readCSV reads an array of strings in csv form .
// skip preceding whitespace // err = ErrInvalidSelector // not open parens, bail // the symbol is the comma // exit reading the csv