Skip to content

Commit 90cb7dc

Browse files
authored
Add JSON array path notation support for empty brackets [] (#100)
1 parent f5f6652 commit 90cb7dc

File tree

2 files changed

+51
-107
lines changed

2 files changed

+51
-107
lines changed

parser/expression.go

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,12 +1489,59 @@ func (p *Parser) parseIsExpression(left ast.Expression) ast.Expression {
14891489
}
14901490

14911491
func (p *Parser) parseArrayAccess(left ast.Expression) ast.Expression {
1492+
pos := p.current.Pos
1493+
p.nextToken() // skip [
1494+
1495+
// Check for empty brackets [] - this is JSON array path notation
1496+
// json.arr[].field becomes Identifier json.arr.:`Array(JSON)`.field
1497+
if p.currentIs(token.RBRACKET) {
1498+
p.nextToken() // skip ]
1499+
1500+
if ident, ok := left.(*ast.Identifier); ok {
1501+
// Append the JSON array type notation to the identifier
1502+
ident.Parts = append(ident.Parts, ":`Array(JSON)`")
1503+
1504+
// Continue parsing any dot accesses that follow
1505+
for p.currentIs(token.DOT) {
1506+
p.nextToken() // skip .
1507+
1508+
if p.currentIs(token.CARET) {
1509+
// Handle JSON path parent access: x.^c0
1510+
p.nextToken() // skip ^
1511+
if p.currentIs(token.IDENT) || p.current.Token.IsKeyword() {
1512+
ident.Parts = append(ident.Parts, "^"+p.current.Value)
1513+
p.nextToken()
1514+
} else {
1515+
break
1516+
}
1517+
} else if p.currentIs(token.IDENT) || p.current.Token.IsKeyword() {
1518+
ident.Parts = append(ident.Parts, p.current.Value)
1519+
p.nextToken()
1520+
1521+
// Check for nested empty array access (e.g., arr[].nested[].field)
1522+
if p.currentIs(token.LBRACKET) {
1523+
return p.parseArrayAccess(ident)
1524+
}
1525+
} else {
1526+
break
1527+
}
1528+
}
1529+
return ident
1530+
}
1531+
1532+
// Not an identifier, fall through to create ArrayAccess with nil index
1533+
return &ast.ArrayAccess{
1534+
Position: pos,
1535+
Array: left,
1536+
Index: nil,
1537+
}
1538+
}
1539+
1540+
// Regular array access with index expression
14921541
expr := &ast.ArrayAccess{
1493-
Position: p.current.Pos,
1542+
Position: pos,
14941543
Array: left,
14951544
}
1496-
1497-
p.nextToken() // skip [
14981545
expr.Index = p.parseExpression(LOWEST)
14991546
p.expect(token.RBRACKET)
15001547

Lines changed: 1 addition & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt117": true,
4-
"stmt119": true,
5-
"stmt121": true,
6-
"stmt123": true,
7-
"stmt125": true,
8-
"stmt127": true,
9-
"stmt129": true,
10-
"stmt131": true,
11-
"stmt133": true,
12-
"stmt139": true,
13-
"stmt141": true,
14-
"stmt143": true,
15-
"stmt145": true,
16-
"stmt155": true,
17-
"stmt157": true,
18-
"stmt159": true,
19-
"stmt161": true,
20-
"stmt163": true,
21-
"stmt165": true,
22-
"stmt167": true,
23-
"stmt169": true,
24-
"stmt171": true,
25-
"stmt173": true,
26-
"stmt175": true,
27-
"stmt177": true,
28-
"stmt185": true,
29-
"stmt187": true,
30-
"stmt189": true,
31-
"stmt191": true,
32-
"stmt193": true,
33-
"stmt195": true,
34-
"stmt197": true,
35-
"stmt199": true,
36-
"stmt201": true,
37-
"stmt207": true,
38-
"stmt209": true,
39-
"stmt21": true,
40-
"stmt211": true,
41-
"stmt213": true,
42-
"stmt223": true,
43-
"stmt225": true,
44-
"stmt227": true,
45-
"stmt229": true,
46-
"stmt23": true,
47-
"stmt231": true,
48-
"stmt233": true,
49-
"stmt235": true,
50-
"stmt237": true,
51-
"stmt239": true,
52-
"stmt241": true,
53-
"stmt243": true,
54-
"stmt245": true,
55-
"stmt25": true,
56-
"stmt253": true,
57-
"stmt255": true,
58-
"stmt257": true,
59-
"stmt259": true,
60-
"stmt261": true,
61-
"stmt263": true,
62-
"stmt265": true,
63-
"stmt267": true,
64-
"stmt269": true,
65-
"stmt27": true,
66-
"stmt275": true,
67-
"stmt277": true,
68-
"stmt279": true,
69-
"stmt281": true,
70-
"stmt29": true,
71-
"stmt291": true,
72-
"stmt293": true,
73-
"stmt295": true,
74-
"stmt297": true,
75-
"stmt299": true,
76-
"stmt301": true,
77-
"stmt303": true,
78-
"stmt305": true,
79-
"stmt307": true,
80-
"stmt309": true,
81-
"stmt31": true,
82-
"stmt311": true,
83-
"stmt313": true,
84-
"stmt33": true,
85-
"stmt35": true,
86-
"stmt37": true,
87-
"stmt43": true,
88-
"stmt45": true,
89-
"stmt47": true,
90-
"stmt49": true,
91-
"stmt59": true,
92-
"stmt61": true,
93-
"stmt63": true,
94-
"stmt65": true,
95-
"stmt67": true,
96-
"stmt69": true,
97-
"stmt71": true,
98-
"stmt73": true,
99-
"stmt75": true,
100-
"stmt77": true,
101-
"stmt79": true,
102-
"stmt81": true
103-
}
104-
}
1+
{}

0 commit comments

Comments
 (0)