Parse the operator + value tail shared by every condition subject * (var[.prop] and multi-arg functions like coalesce(...)): IS [NOT] NULL, * IN [...], or a comparison operator with a literal value. */
| 1076 | * (var[.prop] and multi-arg functions like coalesce(...)): IS [NOT] NULL, |
| 1077 | * IN [...], or a comparison operator with a literal value. */ |
| 1078 | static cbm_expr_t *parse_condition_op(parser_t *p, cbm_condition_t *c) { |
| 1079 | /* IS NULL / IS NOT NULL */ |
| 1080 | if (check(p, TOK_IS)) { |
| 1081 | advance(p); |
| 1082 | if (match(p, TOK_NOT)) { |
| 1083 | c->op = heap_strdup("IS NOT NULL"); |
| 1084 | expect(p, TOK_NULL_KW); |
| 1085 | } else { |
| 1086 | expect(p, TOK_NULL_KW); |
| 1087 | c->op = heap_strdup("IS NULL"); |
| 1088 | } |
| 1089 | return expr_leaf(*c); |
| 1090 | } |
| 1091 | |
| 1092 | /* IN [...] */ |
| 1093 | if (check(p, TOK_IN)) { |
| 1094 | cbm_expr_t *e = parse_in_list(p, c); |
| 1095 | if (!e) { |
| 1096 | cond_func_fields_free(c); |
| 1097 | } |
| 1098 | return e; |
| 1099 | } |
| 1100 | |
| 1101 | /* Standard operators */ |
| 1102 | c->op = parse_comparison_op(p); |
| 1103 | if (!c->op) { |
| 1104 | snprintf(p->error, sizeof(p->error), "unexpected operator at pos %d", peek(p)->pos); |
| 1105 | cond_func_fields_free(c); |
| 1106 | safe_str_free(&c->variable); |
| 1107 | safe_str_free(&c->property); |
| 1108 | safe_str_free(&c->coalesce_default); |
| 1109 | return NULL; |
| 1110 | } |
| 1111 | |
| 1112 | /* Value */ |
| 1113 | if (check(p, TOK_STRING) || check(p, TOK_NUMBER)) { |
| 1114 | c->value = heap_strdup(advance(p)->text); |
| 1115 | } else if (check(p, TOK_TRUE)) { |
| 1116 | advance(p); |
| 1117 | c->value = heap_strdup("true"); |
| 1118 | } else if (check(p, TOK_FALSE)) { |
| 1119 | advance(p); |
| 1120 | c->value = heap_strdup("false"); |
| 1121 | } else { |
| 1122 | snprintf(p->error, sizeof(p->error), "expected value at pos %d", peek(p)->pos); |
| 1123 | cond_func_fields_free(c); |
| 1124 | safe_str_free(&c->variable); |
| 1125 | safe_str_free(&c->property); |
| 1126 | safe_str_free(&c->op); |
| 1127 | safe_str_free(&c->coalesce_default); |
| 1128 | return NULL; |
| 1129 | } |
| 1130 | |
| 1131 | return expr_leaf(*c); |
| 1132 | } |
| 1133 | |
| 1134 | /* parse_condition_lhs result: the label-test form is a complete condition. */ |
| 1135 | enum { COND_LHS_COMPLETE = 1 }; |
no test coverage detected