iter_error(sdb_strbuf_t *errbuf, sdb_ast_iter_t *iter, const char *reason, ...) { char r[1024]; va_list ap; va_start(ap, reason); vsnprintf(r, sizeof(r), reason, ap); va_end(ap); assert((iter->expr->type == SDB_AST_TYPE_OPERATOR) && (! SDB_AST_OP(iter->expr)->left)); sdb_strbuf_sprintf(errbuf, "Invalid iterator %s %s %s %s (%s)", SDB_AST_OP_TO_STRING(iter->kind), SDB_TYPE_TO_STRING(iter->iter->data_type), SDB_AST_OP_TO_STRING(SDB_AST_OP(iter->expr)->kind), SDB_TYPE_TO_STRING(SDB_AST_OP(iter->expr)->right->data_type), r); } /* iter_error */
static void op_error(sdb_strbuf_t *errbuf, sdb_ast_op_t *op, const char *reason) { sdb_strbuf_sprintf(errbuf, "Invalid operation %s %s %s (%s)", SDB_TYPE_TO_STRING(op->left->data_type), SDB_AST_OP_TO_STRING(op->kind), SDB_TYPE_TO_STRING(op->right->data_type), reason); } /* op_error */
sdb_ast_node_t * sdb_ast_iter_create(int kind, sdb_ast_node_t *iter, sdb_ast_node_t *expr) { sdb_ast_iter_t *i; i = SDB_AST_ITER(sdb_object_create(SDB_AST_OP_TO_STRING(kind), iter_type)); if (! i) return NULL; i->super.type = SDB_AST_TYPE_ITERATOR; i->kind = kind; i->iter = iter; i->expr = expr; return SDB_AST_NODE(i); } /* sdb_ast_iter_create */
sdb_ast_node_t * sdb_ast_op_create(int kind, sdb_ast_node_t *left, sdb_ast_node_t *right) { sdb_ast_op_t *op; op = SDB_AST_OP(sdb_object_create(SDB_AST_OP_TO_STRING(kind), op_type)); if (! op) return NULL; op->super.type = SDB_AST_TYPE_OPERATOR; op->kind = kind; op->left = left; op->right = right; return SDB_AST_NODE(op); } /* sdb_ast_op_create */
static int analyze_logical(int context, sdb_ast_op_t *op, sdb_strbuf_t *errbuf) { switch (op->kind) { case SDB_AST_OR: case SDB_AST_AND: if (! SDB_AST_IS_LOGICAL(op->left)) { sdb_strbuf_sprintf(errbuf, "Invalid left operand (%s) " "in %s expression", SDB_AST_TYPE_TO_STRING(op->left), SDB_AST_OP_TO_STRING(op->kind)); return -1; } if (analyze_node(context, op->left, errbuf)) return -1; /* fallthrough */ case SDB_AST_NOT: if (! SDB_AST_IS_LOGICAL(op->right)) { sdb_strbuf_sprintf(errbuf, "Invalid right operand (%s) " "in %s expression", SDB_AST_TYPE_TO_STRING(op->right), SDB_AST_OP_TO_STRING(op->kind)); return -1; } if (analyze_node(context, op->right, errbuf)) return -1; break; case SDB_AST_LT: case SDB_AST_LE: case SDB_AST_EQ: case SDB_AST_NE: case SDB_AST_GE: case SDB_AST_GT: { if (analyze_node(context, op->left, errbuf)) return -1; if (analyze_node(context, op->right, errbuf)) return -1; if ((op->left->data_type > 0) && (op->right->data_type > 0)) { if (op->left->data_type == op->right->data_type) return 0; op_error(errbuf, op, "type mismatch"); return -1; } if ((op->left->data_type > 0) && (op->left->data_type & SDB_TYPE_ARRAY)) { op_error(errbuf, op, "array not allowed"); return -1; } if ((op->right->data_type > 0) && (op->right->data_type & SDB_TYPE_ARRAY)) { op_error(errbuf, op, "array not allowed"); return -1; } break; } case SDB_AST_REGEX: case SDB_AST_NREGEX: if (analyze_node(context, op->left, errbuf)) return -1; if (analyze_node(context, op->right, errbuf)) return -1; /* all types are supported for the left operand * TODO: introduce a cast operator if it's not a string */ if ((op->right->data_type > 0) && (op->right->data_type != SDB_TYPE_REGEX) && (op->right->data_type != SDB_TYPE_STRING)) { op_error(errbuf, op, "invalid regex"); return -1; } break; case SDB_AST_ISNULL: if (analyze_node(context, op->right, errbuf)) return -1; break; case SDB_AST_IN: if (analyze_node(context, op->left, errbuf)) return -1; if (analyze_node(context, op->right, errbuf)) return -1; if ((op->right->data_type > 0) && (! (op->right->data_type & SDB_TYPE_ARRAY))) { op_error(errbuf, op, "array expected"); return -1; } /* the left operand may be a scalar or an array but the element * type has to match */ if ((op->left->data_type > 0) && (op->right->data_type > 0) && ((op->left->data_type & 0xff) != (op->right->data_type & 0xff))) { op_error(errbuf, op, "type mismatch"); return -1; } break; default: sdb_strbuf_sprintf(errbuf, "Unknown operand type %d", op->kind); return -1; } return 0; } /* analyze_logical */