Skip to content

Commit 66f3e1d

Browse files
kyleconroyclaude
andcommitted
Fix MATCH clause AND handling to create flat left-associative structure
The expected AST for MATCH expressions with AND should flatten all composites into a left-associative chain, not create nested chains. Modified parseGraphMatchChainedExpression to also continue on TokenAnd, which starts a fresh node (not chaining from previous rightNode). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 9ca8720 commit 66f3e1d

2 files changed

Lines changed: 13 additions & 27 deletions

File tree

parser/marshal.go

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6449,33 +6449,13 @@ func (p *Parser) parseGraphMatchPredicate() (*ast.GraphMatchPredicate, error) {
64496449
}
64506450

64516451
// parseGraphMatchAndExpression parses graph match expressions connected by AND
6452+
// Note: AND inside chains is now handled by parseGraphMatchChainedExpression
64526453
func (p *Parser) parseGraphMatchAndExpression() (ast.GraphMatchExpression, error) {
6453-
left, err := p.parseGraphMatchChainedExpression()
6454-
if err != nil {
6455-
return nil, err
6456-
}
6457-
6458-
// Check for AND
6459-
for p.curTok.Type == TokenAnd {
6460-
p.nextToken() // consume AND
6461-
6462-
right, err := p.parseGraphMatchChainedExpression()
6463-
if err != nil {
6464-
return nil, err
6465-
}
6466-
6467-
// Wrap in BooleanBinaryExpression
6468-
left = &ast.BooleanBinaryExpression{
6469-
BinaryExpressionType: "And",
6470-
FirstExpression: left.(ast.BooleanExpression),
6471-
SecondExpression: right.(ast.BooleanExpression),
6472-
}
6473-
}
6474-
6475-
return left, nil
6454+
return p.parseGraphMatchChainedExpression()
64766455
}
64776456

64786457
// parseGraphMatchChainedExpression parses a chain like A-(B)->C-(D)->E
6458+
// Also handles AND which continues the chain but starts a fresh node
64796459
func (p *Parser) parseGraphMatchChainedExpression() (ast.GraphMatchExpression, error) {
64806460
// Parse first composite pattern
64816461
first, rightNode, err := p.parseGraphMatchSingleComposite(nil)
@@ -6485,9 +6465,15 @@ func (p *Parser) parseGraphMatchChainedExpression() (ast.GraphMatchExpression, e
64856465

64866466
var result ast.GraphMatchExpression = first
64876467

6488-
// Check for continuation - if the right node is followed by - or <, it's a chain
6489-
for p.curTok.Type == TokenMinus || p.curTok.Type == TokenLessThan {
6490-
// The previous right node becomes the left node of the next composite
6468+
// Check for continuation - if the right node is followed by -, <, or AND, it's a chain
6469+
for p.curTok.Type == TokenMinus || p.curTok.Type == TokenLessThan || p.curTok.Type == TokenAnd {
6470+
// If AND, continue chain but start with fresh node (not chaining from previous)
6471+
if p.curTok.Type == TokenAnd {
6472+
p.nextToken() // consume AND
6473+
rightNode = nil
6474+
}
6475+
6476+
// The previous right node becomes the left node of the next composite (nil if after AND)
64916477
next, nextRightNode, err := p.parseGraphMatchSingleComposite(rightNode)
64926478
if err != nil {
64936479
return nil, err
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}

0 commit comments

Comments
 (0)