| 1200 | } |
| 1201 | |
| 1202 | static cbm_expr_t *parse_condition_expr(parser_t *p) { |
| 1203 | /* Check for NOT prefix at condition level (e.g. NOT n.name CONTAINS "x") */ |
| 1204 | bool negated = match(p, TOK_NOT); |
| 1205 | |
| 1206 | /* EXISTS { pattern } predicate (anchored single-hop existence). */ |
| 1207 | if (check(p, TOK_EXISTS)) { |
| 1208 | return parse_exists_predicate(p, negated); |
| 1209 | } |
| 1210 | |
| 1211 | cbm_condition_t c = {0}; |
| 1212 | c.negated = negated; |
| 1213 | |
| 1214 | int lhs_rc = parse_condition_lhs(p, &c); |
| 1215 | if (lhs_rc < 0) { |
| 1216 | return NULL; |
| 1217 | } |
| 1218 | if (lhs_rc > 0) { |
| 1219 | /* HAS_LABEL leaf — complete condition, no operator follows */ |
| 1220 | return expr_leaf(c); |
| 1221 | } |
| 1222 | |
| 1223 | return parse_condition_op(p, &c); |
| 1224 | } |
| 1225 | |
| 1226 | /* Atom: ( expr ) | condition */ |
| 1227 | static cbm_expr_t *parse_atom_expr(parser_t *p) { // NOLINT(misc-no-recursion) |
no test coverage detected