Skip to content

Commit 1ce8bb6

Browse files
committed
fixup
1 parent 6fe9281 commit 1ce8bb6

File tree

6 files changed

+188
-432
lines changed

6 files changed

+188
-432
lines changed

pkg/jsonpath/ast.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type Query struct {
2323

2424
var _ Node = DescendantSegment{}
2525

26-
type DescendantKind int
26+
type DescendantSegmentSubKind int
2727

2828
const (
2929
DescendantWildcardSelector = iota
@@ -34,7 +34,7 @@ const (
3434
var _ Segment = DescendantSegment{}
3535

3636
type DescendantSegment struct {
37-
SubKind DescendantKind
37+
SubKind DescendantSegmentSubKind
3838
LongFormInner Segment
3939
}
4040

@@ -52,9 +52,23 @@ func (d DescendantSegment) Kind() Kind {
5252
// (wildcard-selector /
5353
// member-name-shorthand))
5454
type ChildSegment struct {
55-
Kind Kind
55+
SubKind ChildSegmentSubKind
56+
Tokens []TokenInfo
57+
InnerSelector *Selector
5658
}
5759

60+
func (c ChildSegment) Kind() Kind {
61+
return ChildSegmentKind
62+
}
63+
64+
type ChildSegmentSubKind int
65+
66+
const (
67+
ChildSegmentDotWildcard ChildSegmentSubKind = iota
68+
ChildSegmentDotMemberName
69+
ChildSegmentSelector
70+
)
71+
5872
// Expr represents a JSONPath expression.
5973
type Expr interface {
6074
Node

pkg/jsonpath/parser.go

Lines changed: 41 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,24 @@ func NewParser(tokenizer *Tokenizer) *Parser {
2525
// Parse parses the JSONPath tokens and returns the root node of the AST.
2626
//
2727
// jsonpath-query = root-identifier segments
28-
func (p *Parser) Parse() (Node, error) {
28+
func (p *Parser) Parse() error {
2929
if len(p.tokens) == 0 {
30-
return nil, fmt.Errorf("empty JSONPath expression")
30+
return fmt.Errorf("empty JSONPath expression")
3131
}
3232

3333
if p.tokens[p.current].Token != ROOT {
34-
return nil, fmt.Errorf("%s: %w", p.tokenizer.ErrorString(p.tokens[p.current], fmt.Sprintf("unexpected token (expected '$')")), ParseError)
34+
return p.parseFailure(p.tokens[p.current], "expected '$'")
3535
}
3636
p.current++
3737

3838
for p.current < len(p.tokens) {
3939
segment, err := p.parseSegment()
4040
if err != nil {
41-
return nil, err
41+
return err
4242
}
4343
p.segments = append(p.segments, segment)
4444
}
45-
46-
if p.current < len(p.tokens) {
47-
return nil, fmt.Errorf(p.tokenizer.ErrorString(p.tokens[p.current], fmt.Sprintf("unexpected token")))
48-
}
45+
return nil
4946
}
5047

5148
// parseDescendantSegment parses a descendant segment (preceded by "..").
@@ -67,7 +64,7 @@ func (p *Parser) parseDescendantSegment() (*DescendantSegment, error) {
6764
node := &DescendantSegment{SubKind: DescendantDotNameSelector}
6865
p.current += 2
6966
return node, nil
70-
} else if nextToken.Token == BRACE_LEFT {
67+
} else if nextToken.Token == BRACKET_LEFT {
7168
node := &DescendantSegment{SubKind: DescendantLongSelector}
7269
previousCurrent := p.current
7370
p.current += 2
@@ -77,7 +74,7 @@ func (p *Parser) parseDescendantSegment() (*DescendantSegment, error) {
7774
p.current = previousCurrent
7875
return nil, err
7976
}
80-
if p.tokens[p.current].Token != BRACE_RIGHT {
77+
if p.tokens[p.current].Token != BRACKET_RIGHT {
8178
p.current = previousCurrent
8279
return nil, p.parseFailure(p.tokens[p.current], "expected ']'")
8380
}
@@ -91,191 +88,6 @@ func (p *Parser) parseFailure(target TokenInfo, msg string) error {
9188
return errors.New(p.tokenizer.ErrorTokenString(target, msg))
9289
}
9390

94-
// parseSubscriptOrFilter parses a subscript or filter node.
95-
func (p *Parser) parseSubscriptOrFilter() (Expr, error) {
96-
if p.peek(COLON) || p.peek(NUMBER) {
97-
return p.parseSlice()
98-
} else if p.peek(WILDCARD) || p.peek(STRING_LITERAL) || p.peek(STRING) || p.peek(NUMBER) || p.peek(BOOLEAN) || p.peek(NULL) {
99-
return p.parseSubscript()
100-
} else if p.peek(PAREN_LEFT) || p.peek(CURRENT) || p.peek(ROOT) || p.peek(RECURSIVE) {
101-
return p.parseFilter()
102-
} else {
103-
return nil, fmt.Errorf("unexpected token %s at line %d, column %d",
104-
p.tokens[p.current].Literal, p.tokens[p.current].Line, p.tokens[p.current].Column)
105-
}
106-
}
107-
108-
// parseSubscript parses a subscript node.
109-
func (p *Parser) parseSubscript() (*SubscriptNode, error) {
110-
node := &SubscriptNode{Lbrack: p.tokens[p.current]}
111-
p.current++
112-
113-
index, err := p.parseRootQuery()
114-
if err != nil {
115-
return nil, err
116-
}
117-
node.Index = index
118-
119-
if !p.expect(BRACKET_RIGHT) {
120-
return nil, fmt.Errorf("expected ']' at line %d, column %d",
121-
p.tokens[p.current].Line, p.tokens[p.current].Column)
122-
}
123-
node.Rbrack = p.tokens[p.current]
124-
p.current++
125-
126-
return node, nil
127-
}
128-
129-
// parseSlice parses a slice node.
130-
func (p *Parser) parseSlice() (*SliceNode, error) {
131-
node := &SliceNode{Lbrack: p.tokens[p.current]}
132-
p.current++
133-
134-
if p.peek(COLON) {
135-
node.Start = nil
136-
} else {
137-
start, err := p.parseRootQuery()
138-
if err != nil {
139-
return nil, err
140-
}
141-
node.Start = start
142-
}
143-
144-
if !p.expect(COLON) {
145-
return nil, fmt.Errorf("expected ':' at line %d, column %d",
146-
p.tokens[p.current].Line, p.tokens[p.current].Column)
147-
}
148-
node.Colon1 = p.tokens[p.current]
149-
p.current++
150-
151-
if p.peek(COLON) || p.peek(BRACKET_RIGHT) {
152-
node.Finish = nil
153-
} else {
154-
end, err := p.parseRootQuery()
155-
if err != nil {
156-
return nil, err
157-
}
158-
node.Finish = end
159-
}
160-
161-
if p.peek(COLON) {
162-
node.Colon2 = p.tokens[p.current]
163-
p.current++
164-
165-
step, err := p.parseRootQuery()
166-
if err != nil {
167-
return nil, err
168-
}
169-
node.Step = step
170-
}
171-
172-
if !p.expect(BRACKET_RIGHT) {
173-
return nil, fmt.Errorf("expected ']' at line %d, column %d",
174-
p.tokens[p.current].Line, p.tokens[p.current].Column)
175-
}
176-
node.Rbrack = p.tokens[p.current]
177-
p.current++
178-
179-
return node, nil
180-
}
181-
182-
// parseFilter parses a filter node.
183-
func (p *Parser) parseFilter() (*FilterNode, error) {
184-
node := &FilterNode{Lbrack: p.tokens[p.current]}
185-
p.current++
186-
187-
expr, err := p.parseRootQuery()
188-
if err != nil {
189-
return nil, err
190-
}
191-
node.Expr = expr
192-
193-
if !p.expect(BRACKET_RIGHT) {
194-
return nil, fmt.Errorf("expected ']' at line %d, column %d",
195-
p.tokens[p.current].Line, p.tokens[p.current].Column)
196-
}
197-
node.Rbrack = p.tokens[p.current]
198-
p.current++
199-
200-
return node, nil
201-
}
202-
203-
// parseFunctionCall parses a function call node.
204-
func (p *Parser) parseFunctionCall() (*FunctionCallNode, error) {
205-
node := &FunctionCallNode{Name: p.tokens[p.current]}
206-
p.current++
207-
208-
if !p.expect(PAREN_LEFT) {
209-
return nil, fmt.Errorf("expected '(' at line %d, column %d",
210-
p.tokens[p.current].Line, p.tokens[p.current].Column)
211-
}
212-
node.Lparen = p.tokens[p.current]
213-
p.current++
214-
215-
for !p.peek(PAREN_RIGHT) {
216-
arg, err := p.parseRootQuery()
217-
if err != nil {
218-
return nil, err
219-
}
220-
node.Args = append(node.Args, arg)
221-
222-
if p.peek(COMMA) {
223-
p.current++
224-
} else if !p.peek(PAREN_RIGHT) {
225-
return nil, fmt.Errorf("expected ',' or ')' at line %d, column %d",
226-
p.tokens[p.current].Line, p.tokens[p.current].Column)
227-
}
228-
}
229-
230-
if !p.expect(PAREN_RIGHT) {
231-
return nil, fmt.Errorf("expected ')' at line %d, column %d",
232-
p.tokens[p.current].Line, p.tokens[p.current].Column)
233-
}
234-
node.Rparen = p.tokens[p.current]
235-
p.current++
236-
237-
return node, nil
238-
}
239-
240-
// parseComparison parses a comparison node.
241-
func (p *Parser) parseComparison() (*ComparisonNode, error) {
242-
lhs, err := p.parseRootQuery()
243-
if err != nil {
244-
return nil, err
245-
}
246-
247-
if !p.isComparisonOperator(p.tokens[p.current].Token) {
248-
return nil, fmt.Errorf("expected comparison operator at line %d, column %d",
249-
p.tokens[p.current].Line, p.tokens[p.current].Column)
250-
}
251-
operator := p.tokens[p.current]
252-
p.current++
253-
254-
rhs, err := p.parseRootQuery()
255-
if err != nil {
256-
return nil, err
257-
}
258-
259-
return &ComparisonNode{Lhs: lhs, Operator: operator, Rhs: rhs}, nil
260-
}
261-
262-
// parseLiteral parses a literal node (boolean, number, string, or null).
263-
func (p *Parser) parseLiteral() (Expr, error) {
264-
switch p.tokens[p.current].Token {
265-
case BOOLEAN:
266-
return &BooleanNode{Value: p.tokens[p.current]}, nil
267-
case NUMBER:
268-
return &NumberNode{Value: p.tokens[p.current]}, nil
269-
case STRING:
270-
return &StringNode{Value: p.tokens[p.current]}, nil
271-
case NULL:
272-
return &NullNode{Null: p.tokens[p.current]}, nil
273-
default:
274-
return nil, fmt.Errorf("unexpected token %s at line %d, column %d",
275-
p.tokens[p.current].Literal, p.tokens[p.current].Line, p.tokens[p.current].Column)
276-
}
277-
}
278-
27991
// peek returns true if the current token matches the given token type.
28092
func (p *Parser) peek(token Token) bool {
28193
return p.current < len(p.tokens) && p.tokens[p.current].Token == token
@@ -308,21 +120,47 @@ func (p *Parser) parseSegment() (Segment, error) {
308120
}
309121

310122
func (p *Parser) parseChildSegment() (Segment, error) {
123+
// .*
124+
// .STRING_LITERAL
125+
// []
311126
firstToken := p.tokens[p.current]
312127
if firstToken.Token == DOT && p.tokens[p.current+1].Token == WILDCARD {
313128
p.current += 2
314-
return &ChildSegment{: firstToken, Star: p.tokens[p.current]}, nil
129+
return &ChildSegment{SubKind: ChildSegmentDotWildcard, Tokens: []TokenInfo{firstToken, p.tokens[p.current+1]}}, nil
315130
} else if firstToken.Token == DOT && p.tokens[p.current+1].Token == STRING_LITERAL {
316131
p.current += 2
317-
return &DotNameSegment{Dot: firstToken, Name: p.tokens[p.current]}, nil
318-
} else if firstToken.Token == DOT && p.tokens[p.current+1].Token == BRACE_LEFT {
132+
return &ChildSegment{SubKind: ChildSegmentDotMemberName, Tokens: []TokenInfo{firstToken, p.tokens[p.current+1]}}, nil
133+
} else if firstToken.Token == DOT && p.tokens[p.current+1].Token == BRACKET_LEFT {
134+
prior := p.current
319135
p.current += 2
320-
innerSegment, err := p.parseSegment()
136+
innerSegment, err := p.parseSelector()
321137
if err != nil {
138+
p.current = prior
322139
return nil, err
323140
}
324-
if p.tokens[p.current].Token != BRACE_RIGHT {
325-
// .*
326-
// .STRING_LITERAL
327-
// []
141+
if p.tokens[p.current].Token != BRACKET_RIGHT {
142+
prior = p.current
143+
return nil, p.parseFailure(p.tokens[p.current], "expected ']'")
144+
}
145+
return &ChildSegment{SubKind: ChildSegmentSelector, Tokens: []TokenInfo{firstToken, p.tokens[p.current]}, InnerSelector: innerSegment}, nil
146+
}
147+
return nil, p.parseFailure(firstToken, "unexpected token when parsing child segment")
148+
}
149+
150+
type SelectorSubKind int
151+
152+
const (
153+
SelectorSubKindWildcard SelectorSubKind = iota
154+
SelectorSubKindName
155+
SelectorSubKindArraySlice
156+
SelectorSubKindArrayIndex
157+
SelectorSubKindFilter
158+
)
159+
160+
type Selector struct {
161+
SubKind SelectorSubKind
162+
}
163+
164+
func (p *Parser) parseSelector() (*Selector, error) {
165+
return nil, nil
328166
}

0 commit comments

Comments
 (0)