| 1008 | } |
| 1009 | |
| 1010 | static cbm_expr_t *parse_condition_expr(parser_t *p) { |
| 1011 | /* Check for NOT prefix at condition level (e.g. NOT n.name CONTAINS "x") */ |
| 1012 | bool negated = match(p, TOK_NOT); |
| 1013 | |
| 1014 | /* EXISTS { pattern } predicate (anchored single-hop existence). */ |
| 1015 | if (check(p, TOK_EXISTS)) { |
| 1016 | return parse_exists_predicate(p, negated); |
| 1017 | } |
| 1018 | |
| 1019 | const cbm_token_t *var = expect(p, TOK_IDENT); |
| 1020 | if (!var) { |
| 1021 | return NULL; |
| 1022 | } |
| 1023 | |
| 1024 | cbm_condition_t c = {0}; |
| 1025 | c.negated = negated; |
| 1026 | |
| 1027 | /* Label test: WHERE n:Label (openCypher, #241). Modelled as a leaf with |
| 1028 | * op="HAS_LABEL" and value=Label, evaluated against the bound node's label. */ |
| 1029 | if (check(p, TOK_COLON)) { |
| 1030 | advance(p); |
| 1031 | const cbm_token_t *lbl = expect(p, TOK_IDENT); |
| 1032 | if (!lbl) { |
| 1033 | return NULL; |
| 1034 | } |
| 1035 | c.variable = heap_strdup(var->text); |
| 1036 | c.op = heap_strdup("HAS_LABEL"); |
| 1037 | c.value = heap_strdup(lbl->text); |
| 1038 | return expr_leaf(c); |
| 1039 | } |
| 1040 | |
| 1041 | if (match(p, TOK_DOT)) { |
| 1042 | const cbm_token_t *prop = expect(p, TOK_IDENT); |
| 1043 | if (!prop) { |
| 1044 | return NULL; |
| 1045 | } |
| 1046 | c.variable = heap_strdup(var->text); |
| 1047 | c.property = heap_strdup(prop->text); |
| 1048 | } else { |
| 1049 | /* No dot: bare alias (e.g. post-WITH variable like "cnt") */ |
| 1050 | c.variable = heap_strdup(var->text); |
| 1051 | c.property = NULL; |
| 1052 | } |
| 1053 | |
| 1054 | /* IS NULL / IS NOT NULL */ |
| 1055 | if (check(p, TOK_IS)) { |
| 1056 | advance(p); |
| 1057 | if (match(p, TOK_NOT)) { |
| 1058 | c.op = heap_strdup("IS NOT NULL"); |
| 1059 | expect(p, TOK_NULL_KW); |
| 1060 | } else { |
| 1061 | expect(p, TOK_NULL_KW); |
| 1062 | c.op = heap_strdup("IS NULL"); |
| 1063 | } |
| 1064 | return expr_leaf(c); |
| 1065 | } |
| 1066 | |
| 1067 | /* IN [...] */ |
no test coverage detected