+static struct isl_basic_map *add_div_definition(struct isl_stream *s,
+ struct vars *v, struct isl_basic_map *bmap, int k)
+{
+ struct isl_token *tok;
+ int seen_paren = 0;
+ struct isl_vec *aff;
+
+ if (isl_stream_eat(s, '['))
+ goto error;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ goto error;
+ if (tok->type == '(') {
+ seen_paren = 1;
+ isl_token_free(tok);
+ } else
+ isl_stream_push_token(s, tok);
+
+ aff = accept_affine(s, v);
+ if (!aff)
+ goto error;
+
+ isl_seq_cpy(bmap->div[k] + 1, aff->el, aff->size);
+
+ isl_vec_free(aff);
+
+ if (seen_paren && isl_stream_eat(s, ')'))
+ goto error;
+ if (isl_stream_eat(s, '/'))
+ goto error;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ goto error;
+ if (tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expected denominator");
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ isl_int_set(bmap->div[k][0], tok->u.v);
+ isl_token_free(tok);
+
+ if (isl_stream_eat(s, ']'))
+ goto error;
+
+ if (isl_basic_map_add_div_constraints(bmap, k) < 0)
+ goto error;
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static struct isl_basic_map *read_defined_var_list(struct isl_stream *s,
+ struct vars *v, struct isl_basic_map *bmap)
+{
+ struct isl_token *tok;
+
+ while ((tok = isl_stream_next_token(s)) != NULL) {
+ int k;
+ int p;
+ int n = v->n;
+ unsigned total = isl_basic_map_total_dim(bmap);
+
+ if (tok->type != ISL_TOKEN_IDENT)
+ break;
+
+ p = vars_pos(v, tok->u.s, -1);
+ if (p < 0)
+ goto error;
+ if (p < n) {
+ isl_stream_error(s, tok, "expecting unique identifier");
+ goto error;
+ }
+ isl_token_free(tok);
+
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_extend_dim(bmap, isl_dim_copy(bmap->dim),
+ 1, 0, 2);
+
+ if ((k = isl_basic_map_alloc_div(bmap)) < 0)
+ goto error;
+ isl_seq_clr(bmap->div[k], 1 + 1 + total);
+
+ tok = isl_stream_next_token(s);
+ if (tok && tok->type == '=') {
+ isl_token_free(tok);
+ bmap = add_div_definition(s, v, bmap, k);
+ tok = isl_stream_next_token(s);
+ }
+
+ if (!tok || tok->type != ',')
+ break;
+
+ isl_token_free(tok);
+ }
+ if (tok)
+ isl_stream_push_token(s, tok);
+
+ return bmap;
+error:
+ isl_token_free(tok);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static __isl_give isl_basic_map *read_tuple(struct isl_stream *s,
+ __isl_take isl_basic_map *bmap, enum isl_dim_type type, struct vars *v)
+{
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != '[') {
+ isl_stream_error(s, tok, "expecting '['");
+ goto error;
+ }
+ isl_token_free(tok);
+ bmap = read_var_list(s, bmap, type, v);
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ']') {
+ isl_stream_error(s, tok, "expecting ']'");
+ goto error;
+ }
+ isl_token_free(tok);
+
+ return bmap;
+error:
+ if (tok)
+ isl_token_free(tok);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static struct isl_basic_map *add_constraints(struct isl_stream *s,
+ struct vars *v, struct isl_basic_map *bmap);
+
+static struct isl_basic_map *add_exists(struct isl_stream *s,
+ struct vars *v, struct isl_basic_map *bmap)
+{
+ struct isl_token *tok;
+ int n = v->n;
+ int extra;
+ int seen_paren = 0;
+ int i;
+ unsigned total;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ goto error;
+ if (tok->type == '(') {
+ seen_paren = 1;
+ isl_token_free(tok);
+ } else
+ isl_stream_push_token(s, tok);
+
+ bmap = read_defined_var_list(s, v, bmap);
+ if (!bmap)
+ goto error;
+
+ if (isl_stream_eat(s, ':'))
+ goto error;
+ bmap = add_constraints(s, v, bmap);
+ if (seen_paren && isl_stream_eat(s, ')'))
+ goto error;
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static __isl_give isl_basic_map *construct_constraint(
+ __isl_take isl_basic_map *bmap, enum isl_token_type type,
+ isl_int *left, isl_int *right)
+{
+ int k;
+ unsigned len;
+ struct isl_ctx *ctx;
+
+ if (!bmap)
+ return NULL;
+ len = 1 + isl_basic_map_total_dim(bmap);
+ ctx = bmap->ctx;
+
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ if (type == ISL_TOKEN_LE)
+ isl_seq_combine(bmap->ineq[k], ctx->negone, left,
+ ctx->one, right,
+ len);
+ else if (type == ISL_TOKEN_GE)
+ isl_seq_combine(bmap->ineq[k], ctx->one, left,
+ ctx->negone, right,
+ len);
+ else if (type == ISL_TOKEN_LT) {
+ isl_seq_combine(bmap->ineq[k], ctx->negone, left,
+ ctx->one, right,
+ len);
+ isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1);
+ } else if (type == ISL_TOKEN_GT) {
+ isl_seq_combine(bmap->ineq[k], ctx->one, left,
+ ctx->negone, right,
+ len);
+ isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1);
+ } else {
+ isl_seq_combine(bmap->ineq[k], ctx->one, left,
+ ctx->negone, right,
+ len);
+ isl_basic_map_inequality_to_equality(bmap, k);
+ }
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static int is_comparator(struct isl_token *tok)
+{
+ if (!tok)
+ return 0;
+
+ switch (tok->type) {
+ case ISL_TOKEN_LT:
+ case ISL_TOKEN_GT:
+ case ISL_TOKEN_LE:
+ case ISL_TOKEN_GE:
+ case '=':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static struct isl_basic_map *add_constraint(struct isl_stream *s,
+ struct vars *v, struct isl_basic_map *bmap)