pqarrays

Paddy 2016-02-25 Parent:bfe2a4af6bdf Child:9a415db0346a

1:ce9c92fc81ab Go to Latest

pqarrays/parser.go

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.

History
1 package pqarrays
3 import (
4 "errors"
5 )
7 func parse(l *lexer) ([]*string, error) {
8 var parsed []*string
9 pchan := make(chan *string)
10 errchan := make(chan error)
11 done := make(chan struct{})
12 go runParse(l, pchan, errchan, done)
13 for {
14 select {
15 case err := <-errchan:
16 return parsed, err
17 case item := <-pchan:
18 parsed = append(parsed, item)
19 case <-done:
20 return parsed, nil
21 }
22 }
23 }
25 func runParse(l *lexer, parsed chan *string, err chan error, done chan struct{}) {
26 var state parseFunc = parseStart
27 for {
28 var e error
29 state, e = state(l, parsed)
30 if e != nil {
31 err <- e
32 break
33 }
34 if state == nil {
35 break
36 }
37 }
38 close(done)
39 }
41 type parseFunc func(*lexer, chan *string) (parseFunc, error)
43 func parseEOF(l *lexer, parsed chan *string) (parseFunc, error) {
44 tok := l.nextToken()
45 if tok.typ == tokenWhitespace {
46 return parseEOF, nil
47 }
48 if tok.typ != tokenEOF {
49 return nil, errors.New("expected EOF, got " + tok.typ.String())
50 }
51 return nil, nil
52 }
54 func parseStringOrNull(l *lexer, parsed chan *string) (parseFunc, error) {
55 tok := l.nextToken()
56 if tok.typ == tokenWhitespace {
57 return parseStringOrNull, nil
58 } else if tok.typ == tokenString {
59 parsed <- &tok.val
60 return parseSeparatorOrDelim, nil
61 } else if tok.typ == tokenNull {
62 parsed <- nil
63 return parseSeparatorOrDelim, nil
64 }
65 return nil, errors.New("expected string, got " + tok.typ.String())
66 }
68 func parseStringOrNullOrEnd(l *lexer, parsed chan *string) (parseFunc, error) {
69 tok := l.nextToken()
70 if tok.typ == tokenWhitespace {
71 return parseStringOrNullOrEnd, nil
72 } else if tok.typ == tokenString {
73 parsed <- &tok.val
74 return parseSeparatorOrDelim, nil
75 } else if tok.typ == tokenNull {
76 parsed <- nil
77 return parseSeparatorOrDelim, nil
78 } else if tok.typ == tokenArrayEnd {
79 return parseEOF, nil
80 }
81 return nil, errors.New("Expected string or end, got " + tok.typ.String())
82 }
84 func parseSeparatorOrDelim(l *lexer, parsed chan *string) (parseFunc, error) {
85 tok := l.nextToken()
86 if tok.typ == tokenWhitespace {
87 return parseSeparatorOrDelim, nil
88 } else if tok.typ == tokenSeparator {
89 return parseStringOrNull, nil
90 } else if tok.typ == tokenArrayEnd {
91 return parseEOF, nil
92 }
93 return nil, errors.New("expected separator or delim, got " + tok.typ.String())
94 }
96 func parseStart(l *lexer, parsed chan *string) (parseFunc, error) {
97 tok := l.nextToken()
98 if tok.typ == tokenWhitespace {
99 return parseStart, nil
100 } else if tok.typ == tokenArrayStart {
101 return parseStringOrNullOrEnd, nil
102 }
103 return nil, errors.New("expected separator or delim, got " + tok.typ.String())
104 }