+ bmap = isl_basic_map_simplify(bmap);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static struct isl_map *map_read_polylib(struct isl_stream *s, int nparam)
+{
+ struct isl_token *tok;
+ struct isl_token *tok2;
+ int i, n;
+ struct isl_map *map;
+
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return NULL;
+ }
+ tok2 = isl_stream_next_token_on_same_line(s);
+ if (tok2 && tok2->type == ISL_TOKEN_VALUE) {
+ isl_stream_push_token(s, tok2);
+ isl_stream_push_token(s, tok);
+ return isl_map_from_basic_map(basic_map_read_polylib(s, nparam));
+ }
+ if (tok2) {
+ isl_stream_error(s, tok2, "unexpected token");
+ isl_stream_push_token(s, tok2);
+ isl_stream_push_token(s, tok);
+ return NULL;
+ }
+ n = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+
+ isl_assert(s->ctx, n >= 1, return NULL);
+
+ map = isl_map_from_basic_map(basic_map_read_polylib(s, nparam));
+
+ for (i = 1; map && i < n; ++i)
+ map = isl_map_union(map,
+ isl_map_from_basic_map(basic_map_read_polylib(s, nparam)));
+
+ return map;
+}
+
+static int optional_power(struct isl_stream *s)
+{
+ int pow;
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 1;
+ if (tok->type != '^') {
+ isl_stream_push_token(s, tok);
+ return 1;
+ }
+ isl_token_free(tok);
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expecting exponent");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ return 1;
+ }
+ pow = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+ return pow;
+}
+
+static __isl_give isl_div *read_div(struct isl_stream *s,
+ __isl_take isl_dim *dim, struct vars *v)
+{
+ int n;
+ isl_basic_map *bmap;
+
+ n = v->n;
+ bmap = isl_basic_map_universe(dim);
+
+ if (vars_add_anon(v) < 0)
+ goto error;
+ if (read_div_definition(s, v) < 0)
+ goto error;
+ bmap = add_divs(bmap, v);
+ bmap = isl_basic_map_order_divs(bmap);
+ if (!bmap)
+ goto error;
+ vars_drop(v, v->n - n);
+
+ return isl_basic_map_div(bmap, bmap->n_div - 1);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static __isl_give isl_qpolynomial *read_term(struct isl_stream *s,
+ __isl_keep isl_basic_map *bmap, struct vars *v);
+
+static __isl_give isl_qpolynomial *read_factor(struct isl_stream *s,
+ __isl_keep isl_basic_map *bmap, struct vars *v)
+{
+ struct isl_qpolynomial *qp;
+ struct isl_token *tok;
+
+ tok = next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return NULL;
+ }
+ if (tok->type == '(') {
+ int pow;
+
+ isl_token_free(tok);
+ qp = read_term(s, bmap, v);
+ if (!qp)
+ return NULL;
+ if (isl_stream_eat(s, ')'))
+ goto error;
+ pow = optional_power(s);
+ qp = isl_qpolynomial_pow(qp, pow);
+ } else if (tok->type == ISL_TOKEN_VALUE) {
+ struct isl_token *tok2;
+ tok2 = isl_stream_next_token(s);
+ if (tok2 && tok2->type == '/') {
+ isl_token_free(tok2);
+ tok2 = next_token(s);
+ if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok2, "expected denominator");
+ isl_token_free(tok);
+ isl_token_free(tok2);
+ return NULL;
+ }
+ qp = isl_qpolynomial_rat_cst(isl_basic_map_get_dim(bmap),
+ tok->u.v, tok2->u.v);
+ isl_token_free(tok2);
+ } else {
+ isl_stream_push_token(s, tok2);
+ qp = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap),
+ tok->u.v);
+ }
+ isl_token_free(tok);
+ } else if (tok->type == ISL_TOKEN_INFTY) {
+ isl_token_free(tok);
+ qp = isl_qpolynomial_infty(isl_basic_map_get_dim(bmap));
+ } else if (tok->type == ISL_TOKEN_NAN) {
+ isl_token_free(tok);
+ qp = isl_qpolynomial_nan(isl_basic_map_get_dim(bmap));
+ } else if (tok->type == ISL_TOKEN_IDENT) {
+ int n = v->n;
+ int pos = vars_pos(v, tok->u.s, -1);
+ int pow;
+ if (pos < 0) {
+ isl_token_free(tok);
+ return NULL;
+ }
+ if (pos >= n) {
+ vars_drop(v, v->n - n);
+ isl_stream_error(s, tok, "unknown identifier");
+ isl_token_free(tok);
+ return NULL;
+ }
+ isl_token_free(tok);
+ pow = optional_power(s);
+ qp = isl_qpolynomial_var_pow(isl_basic_map_get_dim(bmap), pos, pow);
+ } else if (tok->type == '[') {
+ isl_div *div;
+ int pow;
+
+ isl_stream_push_token(s, tok);
+ div = read_div(s, isl_basic_map_get_dim(bmap), v);
+ pow = optional_power(s);
+ qp = isl_qpolynomial_div_pow(div, pow);
+ } else if (tok->type == '-') {
+ struct isl_qpolynomial *qp2;
+
+ isl_token_free(tok);
+ qp = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap),
+ s->ctx->negone);
+ qp2 = read_factor(s, bmap, v);
+ qp = isl_qpolynomial_mul(qp, qp2);
+ } else {
+ isl_stream_error(s, tok, "unexpected isl_token");
+ isl_stream_push_token(s, tok);
+ return NULL;
+ }
+
+ if (isl_stream_eat_if_available(s, '*') ||
+ isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
+ struct isl_qpolynomial *qp2;
+
+ qp2 = read_factor(s, bmap, v);
+ qp = isl_qpolynomial_mul(qp, qp2);
+ }
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+static __isl_give isl_qpolynomial *read_term(struct isl_stream *s,
+ __isl_keep isl_basic_map *bmap, struct vars *v)
+{
+ struct isl_token *tok;
+ struct isl_qpolynomial *qp;
+
+ qp = read_factor(s, bmap, v);
+
+ for (;;) {
+ tok = next_token(s);
+ if (!tok)
+ return qp;
+
+ if (tok->type == '+') {
+ struct isl_qpolynomial *qp2;
+
+ isl_token_free(tok);
+ qp2 = read_factor(s, bmap, v);
+ qp = isl_qpolynomial_add(qp, qp2);
+ } else if (tok->type == '-') {
+ struct isl_qpolynomial *qp2;
+
+ isl_token_free(tok);
+ qp2 = read_factor(s, bmap, v);
+ qp = isl_qpolynomial_sub(qp, qp2);
+ } else if (tok->type == ISL_TOKEN_VALUE &&
+ isl_int_is_neg(tok->u.v)) {
+ struct isl_qpolynomial *qp2;
+
+ isl_stream_push_token(s, tok);
+ qp2 = read_factor(s, bmap, v);
+ qp = isl_qpolynomial_add(qp, qp2);
+ } else {
+ isl_stream_push_token(s, tok);
+ break;
+ }
+ }
+
+ return qp;