Fix bug parsing empty arrays, make golint and go vet happy.
Add comments to make golint happy. Also, because comments are a good thing to
have.
Turn += 1 and -= 1 into ++ and --, respectively, so golint will be happy.
Fix an improperly formated errorf, where a rune was being treated as a string.
Thanks, go vet!
Fix whitespace parsing, returning the parse functions again instead of just
skipping the one character. Now if we have more than one whitespace character in
a row, they'll all be skipped.
Add a parseStringOrNullOrEnd parse function that will be called after the
tokenArrayStart character, to fix a bug where empty arrays were expecting a
string or null and getting the array end character. This is only valid after
tokenArrayStart, however; in other places where parseSeparatorOrDelim is used,
it wouldn't be appropriate.
Add a parser test for an empty array.
20 tokenError tokenType = iota
30 func (t tokenType) String() string {
49 return "unknown token"
53 type stateFunc func(*lexer) stateFunc
71 func lex(input string) *lexer {
74 tokens: make(chan token),
80 func (l *lexer) nextToken() token {
84 func (l *lexer) run() {
85 for l.state = lexStart; l.state != nil; { // TODO(paddy): default state
90 func (l *lexer) emit(t tokenType) {
92 if len(l.omitted) < 1 {
93 val = l.input[l.start:l.pos]
96 for _, pos := range l.omitted {
97 val += l.input[start:pos]
101 val += l.input[start:l.pos]
104 l.tokens <- token{typ: t, val: val}
106 l.omitted = l.omitted[0:0]
109 func (l *lexer) next() rune {
110 if l.pos >= len(l.input) {
115 r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
120 func (l *lexer) omit() {
121 l.omitted = append(l.omitted, l.pos-1)
124 func (l *lexer) ignore() {
128 func (l *lexer) backup() {
132 func (l *lexer) peek() rune {
138 func (l *lexer) accept(valid string) bool {
139 if strings.IndexRune(valid, l.next()) >= 0 {
146 func (l *lexer) acceptRun(valid string) {
147 for strings.IndexRune(valid, l.next()) >= 0 {
152 func (l *lexer) errorf(format string, args ...interface{}) stateFunc {
153 l.tokens <- token{tokenError, fmt.Sprintf(format, args...)}
157 func (l *lexer) consumeWhitespace() {
158 for unicode.IsSpace(l.peek()) {
162 l.emit(tokenWhitespace)
166 func lexStart(l *lexer) stateFunc {
167 l.consumeWhitespace()
171 func lexArrayStart(l *lexer) stateFunc {
172 if strings.HasPrefix(l.input[l.pos:], leftDelim) {
175 return l.errorf("expected array to start before %s", l.input[l.pos:])
178 func lexLeftDelim(l *lexer) stateFunc {
179 l.pos += len(leftDelim)
180 l.emit(tokenArrayStart)
185 func lexRightDelim(l *lexer) stateFunc {
186 l.pos += len(rightDelim)
187 l.emit(tokenArrayEnd)
192 func lexItem(l *lexer) stateFunc {
193 l.consumeWhitespace()
194 if strings.HasPrefix(l.input[l.pos:], rightDelim) {
197 if strings.HasPrefix(l.input[l.pos:], leftDelim) {
200 switch r := l.peek(); {
202 return l.errorf("unclosed array")
204 return l.errorf("empty item in array")
205 case unicode.IsSpace(r):
206 l.consumeWhitespace()
209 return lexQuotedString
215 func lexQuotedString(l *lexer) stateFunc {
217 l.ignore() // ignore the open quote
219 switch r := l.next(); {
221 return l.errorf("unclosed quoted string")
231 // always skip over the character following a \
234 return l.errorf("unclosed quoted string")
240 func lexString(l *lexer) stateFunc {
242 if strings.HasPrefix(l.input[l.pos:], leftDelim) {
243 return l.errorf(leftDelim + " in unquoted string")
245 if strings.HasPrefix(l.input[l.pos:], rightDelim) {
246 if l.pos <= l.start {
247 return l.errorf(rightDelim + " in unquoted string")
249 if string(l.input[l.start:l.pos]) == "NULL" {
256 switch r := l.next(); {
258 return l.errorf("eof while parsing string")
260 return l.errorf("\" in unquoted string")
261 case unicode.IsSpace(r):
262 return l.errorf("unquoted empty string")
264 return l.errorf("\\ in unquoted string")
267 if l.pos <= l.start {
268 return l.errorf("unquoted empty string")
270 if string(l.input[l.start:l.pos]) == "NULL" {
280 func lexSeparator(l *lexer) stateFunc {
281 if strings.HasPrefix(l.input[l.pos:], rightDelim) {
286 l.emit(tokenSeparator)
289 if l.arrayDepth > 0 {
290 return l.errorf("unclosed array")
296 return l.errorf("expected %s, none found before %s\n", string(separator), l.input[l.pos:])