Skip to content

Commit 1c49f32

Browse files
top level parsing is starting to work for objects
1 parent 18dbfbf commit 1c49f32

File tree

7 files changed

+406
-102
lines changed

7 files changed

+406
-102
lines changed

json/action.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2025 Walter Schulze
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package json
16+
17+
type action byte
18+
19+
const nextAction = action(0)
20+
21+
const downAction = action('d')
22+
23+
const upAction = action('u')

json/errors.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,15 @@
1313
// limitations under the License.
1414

1515
package json
16+
17+
import "errors"
18+
19+
var errDown = errors.New("cannot go Down")
20+
21+
var errPop = errors.New("stack is length zero, cannot go Up")
22+
23+
var errNextShouldBeCalled = errors.New("Next should also be called at the start of parsing, after Down and after Up")
24+
25+
var errDownLeaf = errors.New("cannot call Down in Leaf")
26+
27+
var errDownEOF = errors.New("cannot call Down at EOF")

json/json.go

Lines changed: 214 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
package json
1717

1818
import (
19+
"fmt"
20+
"io"
21+
1922
"github.com/katydid/parser-go-json/json/internal/pool"
2023
"github.com/katydid/parser-go-json/json/parse"
2124
"github.com/katydid/parser-go/parser"
@@ -26,10 +29,10 @@ type Interface interface {
2629
parser.Interface
2730
//Init initialises the parser with a byte buffer containing JSON.
2831
Init(buf []byte) error
29-
Kind() Kind
3032
}
3133

3234
type jsonParser struct {
35+
action action
3336
state state
3437
stack []state
3538
parser parse.Parser
@@ -39,81 +42,258 @@ type jsonParser struct {
3942
// NewParser returns a new JSON parser.
4043
func NewParser() Interface {
4144
return &jsonParser{
42-
pool: pool.New(),
43-
stack: make([]state, 0, 10),
45+
stack: make([]state, 0, 10),
46+
parser: parse.NewParser(nil),
47+
pool: pool.New(),
4448
}
4549
}
4650

4751
func (p *jsonParser) Init(buf []byte) error {
52+
p.parser.Init(buf)
4853
p.pool.FreeAll()
4954
return nil
5055
}
5156

52-
func (p *jsonParser) Kind() Kind {
53-
return p.kind
57+
func (p *jsonParser) nextAtStartState(action action) error {
58+
fmt.Printf("nextAtStartState\n")
59+
switch action {
60+
case nextAction:
61+
// find value type
62+
// if object Next over open
63+
// if array: TODO
64+
parseKind, err := p.parser.Next()
65+
if err != nil {
66+
return err
67+
}
68+
switch parseKind {
69+
case parse.ObjectOpenKind:
70+
p.state.kind = inObjectAtKeyStateKind
71+
parseKindNext, err := p.parser.Next()
72+
if err != nil {
73+
return err
74+
}
75+
if parseKindNext == parse.ObjectCloseKind {
76+
return p.eof()
77+
}
78+
return nil
79+
case parse.ArrayOpenKind:
80+
p.state.kind = inArrayStateKind
81+
panic("TODO")
82+
case parse.NullKind, parse.BoolKind, parse.NumberKind, parse.StringKind:
83+
p.state.kind = inLeafStateKind
84+
return nil
85+
}
86+
panic("unreachable")
87+
case downAction:
88+
return errNextShouldBeCalled
89+
case upAction:
90+
return errNextShouldBeCalled
91+
}
92+
panic("unreachable")
5493
}
5594

56-
func (p *jsonParser) firstNext() error {
57-
parseKind, err := p.parser.Next()
58-
if err != nil {
95+
func (p *jsonParser) nextInLeafState(action action) error {
96+
fmt.Printf("nextInLeafState\n")
97+
switch action {
98+
case nextAction:
99+
// We already parsed the leaf, so there is no next element.
100+
return io.EOF
101+
case downAction:
102+
// Cannot call Down when in leaf, since we are the bottom.
103+
return errDownLeaf
104+
case upAction:
105+
// We can go up, if we are an array element or value for a key in an object.
106+
if err := p.pop(); err != nil {
107+
return err
108+
}
109+
// If we were in an object, then move onto next key.
110+
// If we were in an array, them ove onto the next element.
111+
return p.next()
112+
}
113+
panic("unreachable")
114+
}
115+
116+
func (p *jsonParser) nextAtEOF(action action) error {
117+
fmt.Printf("nextAtEOF\n")
118+
switch action {
119+
case nextAction:
120+
// If Next is called too many times, just keep on return EOF
121+
return io.EOF
122+
case downAction:
123+
// We cannot go down if we are at the EOF
124+
return errDownEOF
125+
case upAction:
126+
// We can go up, if we are an array element or value for a key in an object.
127+
if err := p.pop(); err != nil {
128+
return err
129+
}
130+
// If we were in an object, then move onto next key.
131+
// If we were in an array, them ove onto the next element.
132+
return p.next()
133+
}
134+
panic("unreachable")
135+
}
136+
137+
func (p *jsonParser) nextInObjectAtKeyState(action action) error {
138+
fmt.Printf("nextInObjectAtKeyState\n")
139+
// inObjectAtKeyStateKind represents that we have scanned a key
140+
switch action {
141+
case nextAction:
142+
// We want to skip over value and move onto next key.
143+
// We start by skipping over the value.
144+
if err := p.parser.Skip(); err != nil {
145+
return err
146+
}
147+
// Next we move onto the Next key.
148+
parseKind, err := p.parser.Next()
149+
if parseKind == parse.ObjectCloseKind {
150+
// If the Object has ended, we return eof
151+
return p.eof()
152+
}
59153
return err
154+
case downAction:
155+
// Set the state to be ready to parse to next key, when Up is called.
156+
p.state.kind = inObjectAtValueStateKind
157+
// We do not want to skip over the value, we want to continue into value.
158+
// We start by pushing the current state to the stack.
159+
if err := p.push(); err != nil {
160+
return err
161+
}
162+
// The state is reset to be the start state.
163+
// We can call this' Next method, instead of the parser's Next method.
164+
return p.next()
165+
case upAction:
166+
// We want to skip over value and the rest of the object and move onto the next key.
167+
// We start by skipping over the the value.
168+
if err := p.parser.Skip(); err != nil {
169+
return err
170+
}
171+
// Next we skip over the rest of the object.
172+
if err := p.parser.Skip(); err != nil {
173+
return err
174+
}
175+
// Now we pop the stack
176+
if err := p.pop(); err != nil {
177+
return err
178+
}
179+
// Finally we move onto the next key or element, if we were in an array.
180+
return p.next()
60181
}
61-
switch parseKind {
62-
case parse.ObjectOpenKind:
63-
p.state = inObjectState
64-
case parse.ArrayOpenKind:
65-
p.state = inArrayState
66-
case parse.NullKind, parse.BoolKind, parse.StringKind, parse.NumberKind:
67-
p.state = inLeafState
182+
panic("unreachable")
183+
}
184+
185+
func (p *jsonParser) nextInObjectAtValueState(action action) error {
186+
fmt.Printf("nextInObjectAtValueState\n")
187+
// inObjectAtValueStateKind represents that we have scanned a value and Up was called.
188+
switch action {
189+
case nextAction:
190+
// Up was just called and we need to scan to the Next key.
191+
parseKind, err := p.parser.Next()
192+
if parseKind == parse.ObjectCloseKind {
193+
// If the Object has ended, we return eof
194+
return p.eof()
195+
}
196+
// Set the state to the next key
197+
p.state.kind = inObjectAtKeyStateKind
198+
return err
199+
case downAction:
200+
// We can't call Down right, while at the end of value.
201+
return errDown
202+
case upAction:
203+
// We want to skip over the rest of the object and move onto the next key.
204+
// We skip over the rest of the object.
205+
if err := p.parser.Skip(); err != nil {
206+
return err
207+
}
208+
// Now we pop the stack
209+
if err := p.pop(); err != nil {
210+
return err
211+
}
212+
// Finally we move onto the next key or element, if we were in an array.
213+
return p.next()
68214
}
215+
panic("unreachable")
69216
}
70217

71-
func (p *jsonParser) nextKeyValue() error {
72-
return p.parser.Skip()
218+
func (p *jsonParser) eof() error {
219+
// When EOF is returned also set the state to an EOF state.
220+
// This state allows us to call Up.
221+
p.state.kind = atEOFStateKind
222+
return io.EOF
73223
}
74224

75-
func (p *jsonParser) Next() error {
76-
switch p.state {
77-
case atStartState:
78-
return p.firstNext()
79-
case inObjectState:
80-
return p.nextKeyValue()
81-
case goIntoKeyState:
82-
return p.Next()
225+
func (p *jsonParser) next() error {
226+
fmt.Printf("next\n")
227+
action := p.action
228+
// do not forget to reset action
229+
p.action = nextAction
230+
switch p.state.kind {
231+
case atStartStateKind:
232+
return p.nextAtStartState(action)
233+
case inLeafStateKind:
234+
return p.nextInLeafState(action)
235+
case inArrayStateKind:
236+
panic("TODO")
237+
case inObjectAtKeyStateKind:
238+
return p.nextInObjectAtKeyState(action)
239+
case inObjectAtValueStateKind:
240+
return p.nextInObjectAtValueState(action)
241+
case atEOFStateKind:
242+
return p.nextAtEOF(action)
83243
}
244+
panic("unreachable")
245+
}
246+
247+
func (p *jsonParser) Next() error {
248+
fmt.Printf("Next\n")
249+
return p.next()
84250
}
85251

86252
func (p *jsonParser) Down() {
253+
fmt.Printf("Down\n")
254+
p.action = downAction
255+
}
256+
257+
func (p *jsonParser) Up() {
258+
fmt.Printf("Up\n")
259+
p.action = upAction
260+
}
261+
262+
func (p *jsonParser) push() error {
263+
fmt.Printf("push\n")
87264
// Append the current state to the stack.
88265
p.stack = append(p.stack, p.state)
89-
// Create a new state.
90-
switch p.state {
91-
case inObjectState:
92-
p.state = goIntoKeyState
93-
case inArrayState:
94-
p.state = goIntoElemState
95-
}
266+
p.state.kind = atStartStateKind
267+
return nil
96268
}
97269

98-
func (p *jsonParser) Up() {
270+
func (p *jsonParser) pop() error {
271+
fmt.Printf("pop\n")
272+
if len(p.stack) == 0 {
273+
return errPop
274+
}
99275
top := len(p.stack) - 1
100276
// Set the current state to the state on top of the stack.
101277
p.state = p.stack[top]
102278
// Remove the state on the top the stack from the stack,
103279
// but do it in a way that keeps the capacity,
104280
// so we can reuse it the next time Down is called.
105281
p.stack = p.stack[:top]
282+
return nil
106283
}
107284

108285
func (p *jsonParser) IsLeaf() bool {
109-
return p.state == inLeafState
286+
return p.state.kind == inLeafStateKind
110287
}
111288

112289
func (p *jsonParser) Bool() (bool, error) {
113290
return p.parser.Bool()
114291
}
115292

116293
func (p *jsonParser) Int() (int64, error) {
294+
if p.state.kind == inArrayStateKind {
295+
return p.state.arrayIndex, nil
296+
}
117297
return p.parser.Int()
118298
}
119299

0 commit comments

Comments
 (0)