Skip to content

Commit 4c34e6d

Browse files
add support for arrays
1 parent 1c49f32 commit 4c34e6d

File tree

7 files changed

+261
-19
lines changed

7 files changed

+261
-19
lines changed

json/internal/testrun/testrun.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func parseValue(parser InitParser, input string) (string, error) {
4747
return "", fmt.Errorf("walk error: %v", err)
4848
}
4949
if len(jout) != 1 {
50-
return "", fmt.Errorf("expected one node")
50+
return "", fmt.Errorf("expected one node, but got %v", jout)
5151
}
5252
if len(jout[0].Children) != 0 {
5353
return "", fmt.Errorf("did not expected any children")

json/json.go

Lines changed: 121 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ func NewParser() Interface {
5050

5151
func (p *jsonParser) Init(buf []byte) error {
5252
p.parser.Init(buf)
53+
p.action = nextAction
54+
p.state = state{}
55+
p.stack = p.stack[:0]
5356
p.pool.FreeAll()
5457
return nil
5558
}
@@ -58,9 +61,6 @@ func (p *jsonParser) nextAtStartState(action action) error {
5861
fmt.Printf("nextAtStartState\n")
5962
switch action {
6063
case nextAction:
61-
// find value type
62-
// if object Next over open
63-
// if array: TODO
6464
parseKind, err := p.parser.Next()
6565
if err != nil {
6666
return err
@@ -77,8 +77,16 @@ func (p *jsonParser) nextAtStartState(action action) error {
7777
}
7878
return nil
7979
case parse.ArrayOpenKind:
80-
p.state.kind = inArrayStateKind
81-
panic("TODO")
80+
p.state.kind = inArrayIndexStateKind
81+
parseKindNext, err := p.parser.Next()
82+
if err != nil {
83+
return err
84+
}
85+
if parseKindNext == parse.ArrayCloseKind {
86+
return p.eof()
87+
}
88+
p.state.arrayElemKind = parseKindNext
89+
return nil
8290
case parse.NullKind, parse.BoolKind, parse.NumberKind, parse.StringKind:
8391
p.state.kind = inLeafStateKind
8492
return nil
@@ -215,6 +223,108 @@ func (p *jsonParser) nextInObjectAtValueState(action action) error {
215223
panic("unreachable")
216224
}
217225

226+
func (p *jsonParser) nextInArrayIndexState(action action) error {
227+
fmt.Printf("nextInArrayIndexState\n")
228+
// inArrayIndexState represents that we have scanned an element, if it was null, bool, number or string and the first key of an object or .
229+
switch action {
230+
case nextAction:
231+
p.state.arrayIndex += 1
232+
switch p.state.arrayElemKind {
233+
case parse.ObjectOpenKind, parse.ArrayOpenKind:
234+
if err := p.parser.Skip(); err != nil {
235+
return err
236+
}
237+
case parse.NullKind, parse.BoolKind, parse.NumberKind, parse.StringKind:
238+
default:
239+
panic("unreachable")
240+
}
241+
parseKind, err := p.parser.Next()
242+
if err != nil {
243+
return err
244+
}
245+
if parseKind == parse.ArrayCloseKind {
246+
return p.eof()
247+
}
248+
p.state.arrayElemKind = parseKind
249+
return nil
250+
case downAction:
251+
// We are at an array element that we are representing as an index.
252+
// We do not need parse another thing, simply update the state.
253+
p.state.kind = inArrayAfterIndexStateKind
254+
if err := p.push(); err != nil {
255+
return err
256+
}
257+
switch p.state.arrayElemKind {
258+
case parse.ObjectOpenKind:
259+
p.state.kind = inObjectAtKeyStateKind
260+
parseKindNext, err := p.parser.Next()
261+
if err != nil {
262+
return err
263+
}
264+
if parseKindNext == parse.ObjectCloseKind {
265+
return p.eof()
266+
}
267+
return nil
268+
case parse.ArrayOpenKind:
269+
p.state.kind = inArrayIndexStateKind
270+
parseKindNext, err := p.parser.Next()
271+
if err != nil {
272+
return err
273+
}
274+
if parseKindNext == parse.ArrayCloseKind {
275+
return p.eof()
276+
}
277+
p.state.arrayElemKind = parseKindNext
278+
return nil
279+
case parse.NullKind, parse.BoolKind, parse.NumberKind, parse.StringKind:
280+
p.state.kind = inLeafStateKind
281+
return nil
282+
}
283+
panic("unreachable")
284+
case upAction:
285+
// Skip the rest of the array
286+
if err := p.parser.Skip(); err != nil {
287+
return err
288+
}
289+
if err := p.pop(); err != nil {
290+
return err
291+
}
292+
return p.next()
293+
}
294+
panic("unreachable")
295+
}
296+
297+
func (p *jsonParser) nextInArrayAfterIndexState(action action) error {
298+
fmt.Printf("nextInArrayAfterIndexState\n")
299+
// This is after Up was called on an element.
300+
switch action {
301+
case nextAction:
302+
p.state.arrayIndex += 1
303+
parseKind, err := p.parser.Next()
304+
if err != nil {
305+
return err
306+
}
307+
if parseKind == parse.ArrayCloseKind {
308+
return p.eof()
309+
}
310+
p.state.kind = inArrayIndexStateKind
311+
p.state.arrayElemKind = parseKind
312+
return nil
313+
case downAction:
314+
return errDown
315+
case upAction:
316+
// Skip the rest of the array
317+
if err := p.parser.Skip(); err != nil {
318+
return err
319+
}
320+
if err := p.pop(); err != nil {
321+
return err
322+
}
323+
return p.next()
324+
}
325+
panic("unreachable")
326+
}
327+
218328
func (p *jsonParser) eof() error {
219329
// When EOF is returned also set the state to an EOF state.
220330
// This state allows us to call Up.
@@ -232,8 +342,10 @@ func (p *jsonParser) next() error {
232342
return p.nextAtStartState(action)
233343
case inLeafStateKind:
234344
return p.nextInLeafState(action)
235-
case inArrayStateKind:
236-
panic("TODO")
345+
case inArrayIndexStateKind:
346+
return p.nextInArrayIndexState(action)
347+
case inArrayAfterIndexStateKind:
348+
return p.nextInArrayAfterIndexState(action)
237349
case inObjectAtKeyStateKind:
238350
return p.nextInObjectAtKeyState(action)
239351
case inObjectAtValueStateKind:
@@ -264,6 +376,7 @@ func (p *jsonParser) push() error {
264376
// Append the current state to the stack.
265377
p.stack = append(p.stack, p.state)
266378
p.state.kind = atStartStateKind
379+
p.state.arrayIndex = 0
267380
return nil
268381
}
269382

@@ -291,7 +404,7 @@ func (p *jsonParser) Bool() (bool, error) {
291404
}
292405

293406
func (p *jsonParser) Int() (int64, error) {
294-
if p.state.kind == inArrayStateKind {
407+
if p.state.kind == inArrayIndexStateKind {
295408
return p.state.arrayIndex, nil
296409
}
297410
return p.parser.Int()

json/json_test.go

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,52 @@
1515
// Package json contains the implementation of a JSON parser.
1616
package json
1717

18-
import "testing"
18+
import (
19+
"fmt"
20+
"testing"
21+
)
22+
23+
func TestParseString(t *testing.T) {
24+
str := `"a"`
25+
p := NewParser()
26+
if err := p.Init([]byte(str)); err != nil {
27+
t.Fatal(err)
28+
}
29+
assertNoErr(t, p.Next)
30+
if !p.IsLeaf() {
31+
t.Fatalf("expected leaf")
32+
}
33+
expect(t, p.String, "a")
34+
expectEOF(t, p.Next)
35+
}
36+
37+
func TestParseInt(t *testing.T) {
38+
str := `-1`
39+
p := NewParser()
40+
if err := p.Init([]byte(str)); err != nil {
41+
t.Fatal(err)
42+
}
43+
assertNoErr(t, p.Next)
44+
if !p.IsLeaf() {
45+
t.Fatalf("expected leaf")
46+
}
47+
expect(t, p.Int, -1)
48+
expectEOF(t, p.Next)
49+
}
50+
51+
func TestParseDouble(t *testing.T) {
52+
str := `1.1`
53+
p := NewParser()
54+
if err := p.Init([]byte(str)); err != nil {
55+
t.Fatal(err)
56+
}
57+
assertNoErr(t, p.Next)
58+
if !p.IsLeaf() {
59+
t.Fatalf("expected leaf")
60+
}
61+
expect(t, p.Double, 1.1)
62+
expectEOF(t, p.Next)
63+
}
1964

2065
func TestParseObjectKeys(t *testing.T) {
2166
str := `{"a":1, "b":{"c":3}, "d":4}`
@@ -82,3 +127,83 @@ func TestParseObjectValues(t *testing.T) {
82127
expect(t, p.String, "d")
83128
expectEOF(t, p.Next)
84129
}
130+
131+
func TestParseArrayIndexes(t *testing.T) {
132+
str := `["a", true, [1,2], {"a":1}]`
133+
p := NewParser()
134+
if err := p.Init([]byte(str)); err != nil {
135+
t.Fatal(err)
136+
}
137+
assertNoErr(t, p.Next)
138+
expect(t, p.Int, 0)
139+
assertNoErr(t, p.Next)
140+
expect(t, p.Int, 1)
141+
assertNoErr(t, p.Next)
142+
expect(t, p.Int, 2)
143+
assertNoErr(t, p.Next)
144+
expect(t, p.Int, 3)
145+
expectEOF(t, p.Next)
146+
}
147+
148+
func TestParseArrayElements(t *testing.T) {
149+
str := `["a", true, {"a":97}, [10,20]]`
150+
p := NewParser()
151+
if err := p.Init([]byte(str)); err != nil {
152+
t.Fatal(err)
153+
}
154+
155+
fmt.Printf("first element\n")
156+
assertNoErr(t, p.Next)
157+
expect(t, p.Int, 0)
158+
p.Down()
159+
assertNoErr(t, p.Next)
160+
expect(t, p.String, "a")
161+
expectEOF(t, p.Next)
162+
p.Up()
163+
164+
fmt.Printf("second element\n")
165+
assertNoErr(t, p.Next)
166+
expect(t, p.Int, 1)
167+
p.Down()
168+
assertNoErr(t, p.Next)
169+
expect(t, p.Bool, true)
170+
expectEOF(t, p.Next)
171+
p.Up()
172+
173+
fmt.Printf("third element\n")
174+
assertNoErr(t, p.Next)
175+
expect(t, p.Int, 2)
176+
p.Down()
177+
assertNoErr(t, p.Next)
178+
expect(t, p.String, "a")
179+
p.Down()
180+
assertNoErr(t, p.Next)
181+
expect(t, p.Int, 97)
182+
expectEOF(t, p.Next)
183+
p.Up()
184+
expectEOF(t, p.Next)
185+
p.Up()
186+
187+
fmt.Printf("fourth element\n")
188+
assertNoErr(t, p.Next)
189+
expect(t, p.Int, 3)
190+
p.Down()
191+
assertNoErr(t, p.Next)
192+
expect(t, p.Int, 0)
193+
p.Down()
194+
assertNoErr(t, p.Next)
195+
expect(t, p.Int, 10)
196+
expectEOF(t, p.Next)
197+
p.Up()
198+
assertNoErr(t, p.Next)
199+
expect(t, p.Int, 1)
200+
p.Down()
201+
assertNoErr(t, p.Next)
202+
expect(t, p.Int, 20)
203+
expectEOF(t, p.Next)
204+
p.Up()
205+
expectEOF(t, p.Next)
206+
p.Up()
207+
208+
expectEOF(t, p.Next)
209+
}

json/manual_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ func TestIntWithExponent(t *testing.T) {
7676
if !parser.IsLeaf() {
7777
t.Fatal("incorrect walk, please adjust the path above")
7878
}
79-
if i, err := parser.Int(); err != nil {
79+
if d, err := parser.Double(); err != nil {
8080
t.Fatalf("did not expect error %v", err)
81-
} else if i != 1e+08 {
82-
t.Fatalf("got %d", i)
81+
} else if d != 1e+08 {
82+
t.Fatalf("got %v", d)
8383
}
8484
}
8585

json/state.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@
1414

1515
package json
1616

17+
import "github.com/katydid/parser-go-json/json/parse"
18+
1719
type state struct {
18-
kind stateKind
19-
arrayIndex int64
20+
kind stateKind
21+
arrayElemKind parse.Kind
22+
arrayIndex int64
2023
}
2124

2225
type stateKind byte
@@ -25,7 +28,8 @@ const atStartStateKind = stateKind(0)
2528

2629
const inLeafStateKind = stateKind('l')
2730

28-
const inArrayStateKind = stateKind('[')
31+
const inArrayIndexStateKind = stateKind('i')
32+
const inArrayAfterIndexStateKind = stateKind('a')
2933

3034
const inObjectAtKeyStateKind = stateKind('k')
3135
const inObjectAtValueStateKind = stateKind('v')

json/table_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ func TestValues(t *testing.T) {
3131
testrun.EqualValue(t, p, "1.123", "1.123")
3232
testrun.EqualValue(t, p, "1.1e1", "11")
3333
testrun.EqualValue(t, p, "1.1e-1", "0.11")
34-
testrun.EqualValue(t, p, "1.1e10", "11000000000")
35-
testrun.EqualValue(t, p, "1.1e+10", "11000000000")
34+
testrun.EqualValue(t, p, "1.1e10", "1.1e+10")
35+
testrun.EqualValue(t, p, "1.1e+10", "1.1e+10")
3636
testrun.EqualValue(t, p, `"a"`, "a")
3737
testrun.EqualValue(t, p, `"abc"`, "abc")
3838
testrun.EqualValue(t, p, `""`, "")

json/token/tokenizer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func (t *tokenizer) tokenizeNumber() error {
181181
if err != nil {
182182
t.tokenKind = TooLargeNumberKind
183183
// scan already passed, so we know this is a valid number.
184-
// The number is just too large represent in 64 bits.
184+
// The number is just too large represent in 64 float bits.
185185
return nil
186186
}
187187
t.tokenKind = FractionNumberKind

0 commit comments

Comments
 (0)