Support pattern expressions in WHERE clause via GLR parser by gregfelice · Pull Request #2360 · apache/age

@gregfelice @claude

…che#1577)

Enable bare graph patterns as boolean expressions in WHERE clauses:

  MATCH (a:Person), (b:Person)
  WHERE (a)-[:KNOWS]->(b)        -- now valid, equivalent to EXISTS(...)
  RETURN a.name, b.name

Previously, this required wrapping in EXISTS():
  WHERE EXISTS((a)-[:KNOWS]->(b))

The bare pattern syntax is standard openCypher and is used extensively
in Neo4j.  Its absence was the most frequently cited migration blocker.

Implementation approach:
- Switch the Cypher parser from LALR(1) to Bison GLR mode.  GLR handles
  the inherent ambiguity between parenthesized expressions '(' expr ')'
  and graph path nodes '(' var_name label_opt props ')' by forking the
  parse stack and discarding the failing path.
- Add anonymous_path as an expr_atom alternative with %dprec 1 (lower
  priority than expression path at %dprec 2).  The action wraps the
  pattern in a cypher_sub_pattern + EXISTS SubLink, reusing the same
  transform_cypher_sub_pattern() machinery as explicit EXISTS().
- Extract make_exists_pattern_sublink() helper shared by both
  EXISTS(pattern) and bare pattern rules.
- Fix YYLLOC_DEFAULT to use YYRHSLOC() for GLR compatibility.
- %dprec annotations on expr_var/var_name_opt resolve the reduce/reduce
  conflict between expression variables and pattern node variables.

Conflict budget: 7 shift/reduce (path extension vs arithmetic on -/<),
3 reduce/reduce (expr_var vs var_name_opt on )/}/=).  All are expected
and handled correctly by GLR forking + %dprec disambiguation.

All 32 regression tests pass (31 existing + 1 new).  New
pattern_expression test covers: bare patterns, NOT patterns, labeled
nodes, AND/OR combinations, left-directed patterns, anonymous nodes,
multi-hop patterns, EXISTS() backward compatibility, and non-pattern
expression regression checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>