LCOV - code coverage report
Current view: top level - metalib_isl - isl_input.c (source / functions) Hit Total Coverage
Test: 2018-10-31_point_maint_greina16.lcov Lines: 0 2277 0.0 %
Date: 2018-11-01 11:27:00 Functions: 0 130 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008-2009 Katholieke Universiteit Leuven
       3             :  * Copyright 2010      INRIA Saclay
       4             :  * Copyright 2012-2013 Ecole Normale Superieure
       5             :  *
       6             :  * Use of this software is governed by the MIT license
       7             :  *
       8             :  * Written by Sven Verdoolaege, K.U.Leuven, Departement
       9             :  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
      10             :  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
      11             :  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
      12             :  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
      13             :  */
      14             : 
      15             : #include <ctype.h>
      16             : #include <stdio.h>
      17             : #include <string.h>
      18             : #include <isl_ctx_private.h>
      19             : #include <isl_map_private.h>
      20             : #include <isl/set.h>
      21             : #include <isl_seq.h>
      22             : #include <isl_stream_private.h>
      23             : #include <isl/obj.h>
      24             : #include "isl_polynomial_private.h"
      25             : #include <isl/union_set.h>
      26             : #include <isl/union_map.h>
      27             : #include <isl_mat_private.h>
      28             : #include <isl_aff_private.h>
      29             : #include <isl_vec_private.h>
      30             : #include <isl/list.h>
      31             : #include <isl_val_private.h>
      32             : 
      33             : struct variable {
      34             :         char                    *name;
      35             :         int                      pos;
      36             :         struct variable         *next;
      37             : };
      38             : 
      39             : struct vars {
      40             :         struct isl_ctx  *ctx;
      41             :         int              n;
      42             :         struct variable *v;
      43             : };
      44             : 
      45           0 : static struct vars *vars_new(struct isl_ctx *ctx)
      46             : {
      47             :         struct vars *v;
      48           0 :         v = isl_alloc_type(ctx, struct vars);
      49           0 :         if (!v)
      50           0 :                 return NULL;
      51           0 :         v->ctx = ctx;
      52           0 :         v->n = 0;
      53           0 :         v->v = NULL;
      54           0 :         return v;
      55             : }
      56             : 
      57           0 : static void variable_free(struct variable *var)
      58             : {
      59           0 :         while (var) {
      60           0 :                 struct variable *next = var->next;
      61           0 :                 free(var->name);
      62           0 :                 free(var);
      63           0 :                 var = next;
      64             :         }
      65           0 : }
      66             : 
      67           0 : static void vars_free(struct vars *v)
      68             : {
      69           0 :         if (!v)
      70           0 :                 return;
      71           0 :         variable_free(v->v);
      72           0 :         free(v);
      73             : }
      74             : 
      75           0 : static void vars_drop(struct vars *v, int n)
      76             : {
      77             :         struct variable *var;
      78             : 
      79           0 :         if (!v || !v->v)
      80           0 :                 return;
      81             : 
      82           0 :         v->n -= n;
      83             : 
      84           0 :         var = v->v;
      85           0 :         while (--n >= 0) {
      86           0 :                 struct variable *next = var->next;
      87           0 :                 free(var->name);
      88           0 :                 free(var);
      89           0 :                 var = next;
      90             :         }
      91           0 :         v->v = var;
      92             : }
      93             : 
      94           0 : static struct variable *variable_new(struct vars *v, const char *name, int len,
      95             :                                 int pos)
      96             : {
      97             :         struct variable *var;
      98           0 :         var = isl_calloc_type(v->ctx, struct variable);
      99           0 :         if (!var)
     100           0 :                 goto error;
     101           0 :         var->name = strdup(name);
     102           0 :         var->name[len] = '\0';
     103           0 :         var->pos = pos;
     104           0 :         var->next = v->v;
     105           0 :         return var;
     106             : error:
     107           0 :         variable_free(v->v);
     108           0 :         return NULL;
     109             : }
     110             : 
     111           0 : static int vars_pos(struct vars *v, const char *s, int len)
     112             : {
     113             :         int pos;
     114             :         struct variable *q;
     115             : 
     116           0 :         if (len == -1)
     117           0 :                 len = strlen(s);
     118           0 :         for (q = v->v; q; q = q->next) {
     119           0 :                 if (strncmp(q->name, s, len) == 0 && q->name[len] == '\0')
     120           0 :                         break;
     121             :         }
     122           0 :         if (q)
     123           0 :                 pos = q->pos;
     124             :         else {
     125           0 :                 pos = v->n;
     126           0 :                 v->v = variable_new(v, s, len, v->n);
     127           0 :                 if (!v->v)
     128           0 :                         return -1;
     129           0 :                 v->n++;
     130             :         }
     131           0 :         return pos;
     132             : }
     133             : 
     134           0 : static int vars_add_anon(struct vars *v)
     135             : {
     136           0 :         v->v = variable_new(v, "", 0, v->n);
     137             : 
     138           0 :         if (!v->v)
     139           0 :                 return -1;
     140           0 :         v->n++;
     141             : 
     142           0 :         return 0;
     143             : }
     144             : 
     145             : /* Obtain next token, with some preprocessing.
     146             :  * In particular, evaluate expressions of the form x^y,
     147             :  * with x and y values.
     148             :  */
     149           0 : static struct isl_token *next_token(__isl_keep isl_stream *s)
     150             : {
     151             :         struct isl_token *tok, *tok2;
     152             : 
     153           0 :         tok = isl_stream_next_token(s);
     154           0 :         if (!tok || tok->type != ISL_TOKEN_VALUE)
     155           0 :                 return tok;
     156           0 :         if (!isl_stream_eat_if_available(s, '^'))
     157           0 :                 return tok;
     158           0 :         tok2 = isl_stream_next_token(s);
     159           0 :         if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
     160           0 :                 isl_stream_error(s, tok2, "expecting constant value");
     161           0 :                 goto error;
     162             :         }
     163             : 
     164           0 :         isl_int_pow_ui(tok->u.v, tok->u.v, isl_int_get_ui(tok2->u.v));
     165             : 
     166           0 :         isl_token_free(tok2);
     167           0 :         return tok;
     168             : error:
     169           0 :         isl_token_free(tok);
     170           0 :         isl_token_free(tok2);
     171           0 :         return NULL;
     172             : }
     173             : 
     174             : /* Read an isl_val from "s".
     175             :  *
     176             :  * The following token sequences are recognized
     177             :  *
     178             :  *      "infty"               ->   infty
     179             :  *      "-" "infty" ->   -infty
     180             :  *      "NaN"         ->   NaN
     181             :  *      n "/" d               ->   n/d
     182             :  *      v               ->   v
     183             :  *
     184             :  * where n, d and v are integer constants.
     185             :  */
     186           0 : __isl_give isl_val *isl_stream_read_val(__isl_keep isl_stream *s)
     187             : {
     188           0 :         struct isl_token *tok = NULL;
     189           0 :         struct isl_token *tok2 = NULL;
     190             :         isl_val *val;
     191             : 
     192           0 :         tok = next_token(s);
     193           0 :         if (!tok) {
     194           0 :                 isl_stream_error(s, NULL, "unexpected EOF");
     195           0 :                 goto error;
     196             :         }
     197           0 :         if (tok->type == ISL_TOKEN_INFTY) {
     198           0 :                 isl_token_free(tok);
     199           0 :                 return isl_val_infty(s->ctx);
     200             :         }
     201           0 :         if (tok->type == '-' &&
     202           0 :             isl_stream_eat_if_available(s, ISL_TOKEN_INFTY)) {
     203           0 :                 isl_token_free(tok);
     204           0 :                 return isl_val_neginfty(s->ctx);
     205             :         }
     206           0 :         if (tok->type == ISL_TOKEN_NAN) {
     207           0 :                 isl_token_free(tok);
     208           0 :                 return isl_val_nan(s->ctx);
     209             :         }
     210           0 :         if (tok->type != ISL_TOKEN_VALUE) {
     211           0 :                 isl_stream_error(s, tok, "expecting value");
     212           0 :                 goto error;
     213             :         }
     214             : 
     215           0 :         if (isl_stream_eat_if_available(s, '/')) {
     216           0 :                 tok2 = next_token(s);
     217           0 :                 if (!tok2) {
     218           0 :                         isl_stream_error(s, NULL, "unexpected EOF");
     219           0 :                         goto error;
     220             :                 }
     221           0 :                 if (tok2->type != ISL_TOKEN_VALUE) {
     222           0 :                         isl_stream_error(s, tok2, "expecting value");
     223           0 :                         goto error;
     224             :                 }
     225           0 :                 val = isl_val_rat_from_isl_int(s->ctx, tok->u.v, tok2->u.v);
     226           0 :                 val = isl_val_normalize(val);
     227             :         } else {
     228           0 :                 val = isl_val_int_from_isl_int(s->ctx, tok->u.v);
     229             :         }
     230             : 
     231           0 :         isl_token_free(tok);
     232           0 :         isl_token_free(tok2);
     233           0 :         return val;
     234             : error:
     235           0 :         isl_token_free(tok);
     236           0 :         isl_token_free(tok2);
     237           0 :         return NULL;
     238             : }
     239             : 
     240             : /* Read an isl_val from "str".
     241             :  */
     242           0 : struct isl_val *isl_val_read_from_str(struct isl_ctx *ctx,
     243             :         const char *str)
     244             : {
     245             :         isl_val *val;
     246           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
     247           0 :         if (!s)
     248           0 :                 return NULL;
     249           0 :         val = isl_stream_read_val(s);
     250           0 :         isl_stream_free(s);
     251           0 :         return val;
     252             : }
     253             : 
     254           0 : static int accept_cst_factor(__isl_keep isl_stream *s, isl_int *f)
     255             : {
     256             :         struct isl_token *tok;
     257             : 
     258           0 :         tok = next_token(s);
     259           0 :         if (!tok || tok->type != ISL_TOKEN_VALUE) {
     260           0 :                 isl_stream_error(s, tok, "expecting constant value");
     261           0 :                 goto error;
     262             :         }
     263             : 
     264           0 :         isl_int_mul(*f, *f, tok->u.v);
     265             : 
     266           0 :         isl_token_free(tok);
     267             : 
     268           0 :         if (isl_stream_eat_if_available(s, '*'))
     269           0 :                 return accept_cst_factor(s, f);
     270             : 
     271           0 :         return 0;
     272             : error:
     273           0 :         isl_token_free(tok);
     274           0 :         return -1;
     275             : }
     276             : 
     277             : /* Given an affine expression aff, return an affine expression
     278             :  * for aff % d, with d the next token on the stream, which is
     279             :  * assumed to be a constant.
     280             :  *
     281             :  * We introduce an integer division q = [aff/d] and the result
     282             :  * is set to aff - d q.
     283             :  */
     284           0 : static __isl_give isl_pw_aff *affine_mod(__isl_keep isl_stream *s,
     285             :         struct vars *v, __isl_take isl_pw_aff *aff)
     286             : {
     287             :         struct isl_token *tok;
     288             :         isl_pw_aff *q;
     289             : 
     290           0 :         tok = next_token(s);
     291           0 :         if (!tok || tok->type != ISL_TOKEN_VALUE) {
     292           0 :                 isl_stream_error(s, tok, "expecting constant value");
     293           0 :                 goto error;
     294             :         }
     295             : 
     296           0 :         q = isl_pw_aff_copy(aff);
     297           0 :         q = isl_pw_aff_scale_down(q, tok->u.v);
     298           0 :         q = isl_pw_aff_floor(q);
     299           0 :         q = isl_pw_aff_scale(q, tok->u.v);
     300             : 
     301           0 :         aff = isl_pw_aff_sub(aff, q);
     302             : 
     303           0 :         isl_token_free(tok);
     304           0 :         return aff;
     305             : error:
     306           0 :         isl_pw_aff_free(aff);
     307           0 :         isl_token_free(tok);
     308           0 :         return NULL;
     309             : }
     310             : 
     311             : static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
     312             :         __isl_take isl_space *space, struct vars *v);
     313             : static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s,
     314             :         __isl_take isl_space *dim, struct vars *v);
     315             : 
     316           0 : static __isl_give isl_pw_aff *accept_minmax(__isl_keep isl_stream *s,
     317             :         __isl_take isl_space *dim, struct vars *v)
     318             : {
     319             :         struct isl_token *tok;
     320           0 :         isl_pw_aff_list *list = NULL;
     321             :         int min;
     322             : 
     323           0 :         tok = isl_stream_next_token(s);
     324           0 :         if (!tok)
     325           0 :                 goto error;
     326           0 :         min = tok->type == ISL_TOKEN_MIN;
     327           0 :         isl_token_free(tok);
     328             : 
     329           0 :         if (isl_stream_eat(s, '('))
     330           0 :                 goto error;
     331             : 
     332           0 :         list = accept_affine_list(s, isl_space_copy(dim), v);
     333           0 :         if (!list)
     334           0 :                 goto error;
     335             : 
     336           0 :         if (isl_stream_eat(s, ')'))
     337           0 :                 goto error;
     338             : 
     339           0 :         isl_space_free(dim);
     340           0 :         return min ? isl_pw_aff_list_min(list) : isl_pw_aff_list_max(list);
     341             : error:
     342           0 :         isl_space_free(dim);
     343           0 :         isl_pw_aff_list_free(list);
     344           0 :         return NULL;
     345             : }
     346             : 
     347             : /* Is "tok" the start of an integer division?
     348             :  */
     349           0 : static int is_start_of_div(struct isl_token *tok)
     350             : {
     351           0 :         if (!tok)
     352           0 :                 return 0;
     353           0 :         if (tok->type == '[')
     354           0 :                 return 1;
     355           0 :         if (tok->type == ISL_TOKEN_FLOOR)
     356           0 :                 return 1;
     357           0 :         if (tok->type == ISL_TOKEN_CEIL)
     358           0 :                 return 1;
     359           0 :         if (tok->type == ISL_TOKEN_FLOORD)
     360           0 :                 return 1;
     361           0 :         if (tok->type == ISL_TOKEN_CEILD)
     362           0 :                 return 1;
     363           0 :         return 0;
     364             : }
     365             : 
     366             : /* Read an integer division from "s" and return it as an isl_pw_aff.
     367             :  *
     368             :  * The integer division can be of the form
     369             :  *
     370             :  *      [<affine expression>]
     371             :  *      floor(<affine expression>)
     372             :  *      ceil(<affine expression>)
     373             :  *      floord(<affine expression>,<denominator>)
     374             :  *      ceild(<affine expression>,<denominator>)
     375             :  */
     376           0 : static __isl_give isl_pw_aff *accept_div(__isl_keep isl_stream *s,
     377             :         __isl_take isl_space *dim, struct vars *v)
     378             : {
     379             :         struct isl_token *tok;
     380           0 :         int f = 0;
     381           0 :         int c = 0;
     382           0 :         int extra = 0;
     383           0 :         isl_pw_aff *pwaff = NULL;
     384             : 
     385           0 :         if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOORD))
     386           0 :                 extra = f = 1;
     387           0 :         else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEILD))
     388           0 :                 extra = c = 1;
     389           0 :         else if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOOR))
     390           0 :                 f = 1;
     391           0 :         else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEIL))
     392           0 :                 c = 1;
     393           0 :         if (f || c) {
     394           0 :                 if (isl_stream_eat(s, '('))
     395           0 :                         goto error;
     396             :         } else {
     397           0 :                 if (isl_stream_eat(s, '['))
     398           0 :                         goto error;
     399             :         }
     400             : 
     401           0 :         pwaff = accept_affine(s, isl_space_copy(dim), v);
     402             : 
     403           0 :         if (extra) {
     404           0 :                 if (isl_stream_eat(s, ','))
     405           0 :                         goto error;
     406             : 
     407           0 :                 tok = next_token(s);
     408           0 :                 if (!tok)
     409           0 :                         goto error;
     410           0 :                 if (tok->type != ISL_TOKEN_VALUE) {
     411           0 :                         isl_stream_error(s, tok, "expected denominator");
     412           0 :                         isl_stream_push_token(s, tok);
     413           0 :                         goto error;
     414             :                 }
     415           0 :                 pwaff = isl_pw_aff_scale_down(pwaff,  tok->u.v);
     416           0 :                 isl_token_free(tok);
     417             :         }
     418             : 
     419           0 :         if (c)
     420           0 :                 pwaff = isl_pw_aff_ceil(pwaff);
     421             :         else
     422           0 :                 pwaff = isl_pw_aff_floor(pwaff);
     423             : 
     424           0 :         if (f || c) {
     425           0 :                 if (isl_stream_eat(s, ')'))
     426           0 :                         goto error;
     427             :         } else {
     428           0 :                 if (isl_stream_eat(s, ']'))
     429           0 :                         goto error;
     430             :         }
     431             : 
     432           0 :         isl_space_free(dim);
     433           0 :         return pwaff;
     434             : error:
     435           0 :         isl_space_free(dim);
     436           0 :         isl_pw_aff_free(pwaff);
     437           0 :         return NULL;
     438             : }
     439             : 
     440           0 : static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
     441             :         __isl_take isl_space *dim, struct vars *v)
     442             : {
     443           0 :         struct isl_token *tok = NULL;
     444           0 :         isl_pw_aff *res = NULL;
     445             : 
     446           0 :         tok = next_token(s);
     447           0 :         if (!tok) {
     448           0 :                 isl_stream_error(s, NULL, "unexpected EOF");
     449           0 :                 goto error;
     450             :         }
     451             : 
     452           0 :         if (tok->type == ISL_TOKEN_AFF) {
     453           0 :                 res = isl_pw_aff_copy(tok->u.pwaff);
     454           0 :                 isl_token_free(tok);
     455           0 :         } else if (tok->type == ISL_TOKEN_IDENT) {
     456           0 :                 int n = v->n;
     457           0 :                 int pos = vars_pos(v, tok->u.s, -1);
     458             :                 isl_aff *aff;
     459             : 
     460           0 :                 if (pos < 0)
     461           0 :                         goto error;
     462           0 :                 if (pos >= n) {
     463           0 :                         vars_drop(v, v->n - n);
     464           0 :                         isl_stream_error(s, tok, "unknown identifier");
     465           0 :                         goto error;
     466             :                 }
     467             : 
     468           0 :                 aff = isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(dim)));
     469           0 :                 if (!aff)
     470           0 :                         goto error;
     471           0 :                 isl_int_set_si(aff->v->el[2 + pos], 1);
     472           0 :                 res = isl_pw_aff_from_aff(aff);
     473           0 :                 isl_token_free(tok);
     474           0 :         } else if (tok->type == ISL_TOKEN_VALUE) {
     475           0 :                 if (isl_stream_eat_if_available(s, '*')) {
     476           0 :                         res = accept_affine_factor(s, isl_space_copy(dim), v);
     477           0 :                         res = isl_pw_aff_scale(res, tok->u.v);
     478             :                 } else {
     479             :                         isl_local_space *ls;
     480             :                         isl_aff *aff;
     481           0 :                         ls = isl_local_space_from_space(isl_space_copy(dim));
     482           0 :                         aff = isl_aff_zero_on_domain(ls);
     483           0 :                         aff = isl_aff_add_constant(aff, tok->u.v);
     484           0 :                         res = isl_pw_aff_from_aff(aff);
     485             :                 }
     486           0 :                 isl_token_free(tok);
     487           0 :         } else if (tok->type == '(') {
     488           0 :                 isl_token_free(tok);
     489           0 :                 tok = NULL;
     490           0 :                 res = accept_affine(s, isl_space_copy(dim), v);
     491           0 :                 if (!res)
     492           0 :                         goto error;
     493           0 :                 if (isl_stream_eat(s, ')'))
     494           0 :                         goto error;
     495           0 :         } else if (is_start_of_div(tok)) {
     496           0 :                 isl_stream_push_token(s, tok);
     497           0 :                 tok = NULL;
     498           0 :                 res = accept_div(s, isl_space_copy(dim), v);
     499           0 :         } else if (tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX) {
     500           0 :                 isl_stream_push_token(s, tok);
     501           0 :                 tok = NULL;
     502           0 :                 res = accept_minmax(s, isl_space_copy(dim), v);
     503             :         } else {
     504           0 :                 isl_stream_error(s, tok, "expecting factor");
     505           0 :                 goto error;
     506             :         }
     507           0 :         if (isl_stream_eat_if_available(s, '%') ||
     508           0 :             isl_stream_eat_if_available(s, ISL_TOKEN_MOD)) {
     509           0 :                 isl_space_free(dim);
     510           0 :                 return affine_mod(s, v, res);
     511             :         }
     512           0 :         if (isl_stream_eat_if_available(s, '*')) {
     513             :                 isl_int f;
     514           0 :                 isl_int_init(f);
     515           0 :                 isl_int_set_si(f, 1);
     516           0 :                 if (accept_cst_factor(s, &f) < 0) {
     517           0 :                         isl_int_clear(f);
     518           0 :                         goto error2;
     519             :                 }
     520           0 :                 res = isl_pw_aff_scale(res, f);
     521           0 :                 isl_int_clear(f);
     522             :         }
     523           0 :         if (isl_stream_eat_if_available(s, '/')) {
     524             :                 isl_int f;
     525           0 :                 isl_int_init(f);
     526           0 :                 isl_int_set_si(f, 1);
     527           0 :                 if (accept_cst_factor(s, &f) < 0) {
     528           0 :                         isl_int_clear(f);
     529           0 :                         goto error2;
     530             :                 }
     531           0 :                 res = isl_pw_aff_scale_down(res, f);
     532           0 :                 isl_int_clear(f);
     533             :         }
     534             : 
     535           0 :         isl_space_free(dim);
     536           0 :         return res;
     537             : error:
     538           0 :         isl_token_free(tok);
     539             : error2:
     540           0 :         isl_pw_aff_free(res);
     541           0 :         isl_space_free(dim);
     542           0 :         return NULL;
     543             : }
     544             : 
     545           0 : static __isl_give isl_pw_aff *add_cst(__isl_take isl_pw_aff *pwaff, isl_int v)
     546             : {
     547             :         isl_aff *aff;
     548             :         isl_space *space;
     549             : 
     550           0 :         space = isl_pw_aff_get_domain_space(pwaff);
     551           0 :         aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
     552           0 :         aff = isl_aff_add_constant(aff, v);
     553             : 
     554           0 :         return isl_pw_aff_add(pwaff, isl_pw_aff_from_aff(aff));
     555             : }
     556             : 
     557             : /* Return a piecewise affine expression defined on the specified domain
     558             :  * that represents NaN.
     559             :  */
     560           0 : static __isl_give isl_pw_aff *nan_on_domain(__isl_keep isl_space *space)
     561             : {
     562             :         isl_local_space *ls;
     563             : 
     564           0 :         ls = isl_local_space_from_space(isl_space_copy(space));
     565           0 :         return isl_pw_aff_nan_on_domain(ls);
     566             : }
     567             : 
     568           0 : static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
     569             :         __isl_take isl_space *space, struct vars *v)
     570             : {
     571           0 :         struct isl_token *tok = NULL;
     572             :         isl_local_space *ls;
     573             :         isl_pw_aff *res;
     574           0 :         int sign = 1;
     575             : 
     576           0 :         ls = isl_local_space_from_space(isl_space_copy(space));
     577           0 :         res = isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls));
     578           0 :         if (!res)
     579           0 :                 goto error;
     580             : 
     581             :         for (;;) {
     582           0 :                 tok = next_token(s);
     583           0 :                 if (!tok) {
     584           0 :                         isl_stream_error(s, NULL, "unexpected EOF");
     585           0 :                         goto error;
     586             :                 }
     587           0 :                 if (tok->type == '-') {
     588           0 :                         sign = -sign;
     589           0 :                         isl_token_free(tok);
     590           0 :                         continue;
     591             :                 }
     592           0 :                 if (tok->type == '(' || is_start_of_div(tok) ||
     593           0 :                     tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX ||
     594           0 :                     tok->type == ISL_TOKEN_IDENT ||
     595           0 :                     tok->type == ISL_TOKEN_AFF) {
     596             :                         isl_pw_aff *term;
     597           0 :                         isl_stream_push_token(s, tok);
     598           0 :                         tok = NULL;
     599           0 :                         term = accept_affine_factor(s,
     600             :                                                     isl_space_copy(space), v);
     601           0 :                         if (sign < 0)
     602           0 :                                 res = isl_pw_aff_sub(res, term);
     603             :                         else
     604           0 :                                 res = isl_pw_aff_add(res, term);
     605           0 :                         if (!res)
     606           0 :                                 goto error;
     607           0 :                         sign = 1;
     608           0 :                 } else if (tok->type == ISL_TOKEN_VALUE) {
     609           0 :                         if (sign < 0)
     610           0 :                                 isl_int_neg(tok->u.v, tok->u.v);
     611           0 :                         if (isl_stream_eat_if_available(s, '*') ||
     612           0 :                             isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
     613             :                                 isl_pw_aff *term;
     614           0 :                                 term = accept_affine_factor(s,
     615             :                                                     isl_space_copy(space), v);
     616           0 :                                 term = isl_pw_aff_scale(term, tok->u.v);
     617           0 :                                 res = isl_pw_aff_add(res, term);
     618           0 :                                 if (!res)
     619           0 :                                         goto error;
     620             :                         } else {
     621           0 :                                 res = add_cst(res, tok->u.v);
     622             :                         }
     623           0 :                         sign = 1;
     624           0 :                 } else if (tok->type == ISL_TOKEN_NAN) {
     625           0 :                         res = isl_pw_aff_add(res, nan_on_domain(space));
     626             :                 } else {
     627           0 :                         isl_stream_error(s, tok, "unexpected isl_token");
     628           0 :                         isl_stream_push_token(s, tok);
     629           0 :                         isl_pw_aff_free(res);
     630           0 :                         isl_space_free(space);
     631           0 :                         return NULL;
     632             :                 }
     633           0 :                 isl_token_free(tok);
     634             : 
     635           0 :                 tok = next_token(s);
     636           0 :                 if (tok && tok->type == '-') {
     637           0 :                         sign = -sign;
     638           0 :                         isl_token_free(tok);
     639           0 :                 } else if (tok && tok->type == '+') {
     640             :                         /* nothing */
     641           0 :                         isl_token_free(tok);
     642           0 :                 } else if (tok && tok->type == ISL_TOKEN_VALUE &&
     643           0 :                            isl_int_is_neg(tok->u.v)) {
     644           0 :                         isl_stream_push_token(s, tok);
     645             :                 } else {
     646           0 :                         if (tok)
     647           0 :                                 isl_stream_push_token(s, tok);
     648           0 :                         break;
     649             :                 }
     650           0 :         }
     651             : 
     652           0 :         isl_space_free(space);
     653           0 :         return res;
     654             : error:
     655           0 :         isl_space_free(space);
     656           0 :         isl_token_free(tok);
     657           0 :         isl_pw_aff_free(res);
     658           0 :         return NULL;
     659             : }
     660             : 
     661             : /* Is "type" the type of a comparison operator between lists
     662             :  * of affine expressions?
     663             :  */
     664           0 : static int is_list_comparator_type(int type)
     665             : {
     666           0 :         switch (type) {
     667             :         case ISL_TOKEN_LEX_LT:
     668             :         case ISL_TOKEN_LEX_GT:
     669             :         case ISL_TOKEN_LEX_LE:
     670             :         case ISL_TOKEN_LEX_GE:
     671           0 :                 return 1;
     672             :         default:
     673           0 :                 return 0;
     674             :         }
     675             : }
     676             : 
     677           0 : static int is_comparator(struct isl_token *tok)
     678             : {
     679           0 :         if (!tok)
     680           0 :                 return 0;
     681           0 :         if (is_list_comparator_type(tok->type))
     682           0 :                 return 1;
     683             : 
     684           0 :         switch (tok->type) {
     685             :         case ISL_TOKEN_LT:
     686             :         case ISL_TOKEN_GT:
     687             :         case ISL_TOKEN_LE:
     688             :         case ISL_TOKEN_GE:
     689             :         case ISL_TOKEN_NE:
     690             :         case '=':
     691           0 :                 return 1;
     692             :         default:
     693           0 :                 return 0;
     694             :         }
     695             : }
     696             : 
     697             : static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
     698             :         struct vars *v, __isl_take isl_map *map, int rational);
     699             : static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
     700             :         __isl_take isl_space *dim, struct vars *v, int rational);
     701             : 
     702             : /* Accept a ternary operator, given the first argument.
     703             :  */
     704           0 : static __isl_give isl_pw_aff *accept_ternary(__isl_keep isl_stream *s,
     705             :         __isl_take isl_map *cond, struct vars *v, int rational)
     706             : {
     707             :         isl_space *dim;
     708           0 :         isl_pw_aff *pwaff1 = NULL, *pwaff2 = NULL, *pa_cond;
     709             : 
     710           0 :         if (!cond)
     711           0 :                 return NULL;
     712             : 
     713           0 :         if (isl_stream_eat(s, '?'))
     714           0 :                 goto error;
     715             : 
     716           0 :         dim = isl_space_wrap(isl_map_get_space(cond));
     717           0 :         pwaff1 = accept_extended_affine(s, dim, v, rational);
     718           0 :         if (!pwaff1)
     719           0 :                 goto error;
     720             : 
     721           0 :         if (isl_stream_eat(s, ':'))
     722           0 :                 goto error;
     723             : 
     724           0 :         dim = isl_pw_aff_get_domain_space(pwaff1);
     725           0 :         pwaff2 = accept_extended_affine(s, dim, v, rational);
     726           0 :         if (!pwaff1)
     727           0 :                 goto error;
     728             : 
     729           0 :         pa_cond = isl_set_indicator_function(isl_map_wrap(cond));
     730           0 :         return isl_pw_aff_cond(pa_cond, pwaff1, pwaff2);
     731             : error:
     732           0 :         isl_map_free(cond);
     733           0 :         isl_pw_aff_free(pwaff1);
     734           0 :         isl_pw_aff_free(pwaff2);
     735           0 :         return NULL;
     736             : }
     737             : 
     738             : /* Set *line and *col to those of the next token, if any.
     739             :  */
     740           0 : static void set_current_line_col(__isl_keep isl_stream *s, int *line, int *col)
     741             : {
     742             :         struct isl_token *tok;
     743             : 
     744           0 :         tok = isl_stream_next_token(s);
     745           0 :         if (!tok)
     746           0 :                 return;
     747             : 
     748           0 :         *line = tok->line;
     749           0 :         *col = tok->col;
     750           0 :         isl_stream_push_token(s, tok);
     751             : }
     752             : 
     753             : /* Push a token encapsulating "pa" onto "s", with the given
     754             :  * line and column.
     755             :  */
     756           0 : static int push_aff(__isl_keep isl_stream *s, int line, int col,
     757             :         __isl_take isl_pw_aff *pa)
     758             : {
     759             :         struct isl_token *tok;
     760             : 
     761           0 :         tok = isl_token_new(s->ctx, line, col, 0);
     762           0 :         if (!tok)
     763           0 :                 goto error;
     764           0 :         tok->type = ISL_TOKEN_AFF;
     765           0 :         tok->u.pwaff = pa;
     766           0 :         isl_stream_push_token(s, tok);
     767             : 
     768           0 :         return 0;
     769             : error:
     770           0 :         isl_pw_aff_free(pa);
     771           0 :         return -1;
     772             : }
     773             : 
     774             : /* Accept an affine expression that may involve ternary operators.
     775             :  * We first read an affine expression.
     776             :  * If it is not followed by a comparison operator, we simply return it.
     777             :  * Otherwise, we assume the affine expression is part of the first
     778             :  * argument of a ternary operator and try to parse that.
     779             :  */
     780           0 : static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
     781             :         __isl_take isl_space *dim, struct vars *v, int rational)
     782             : {
     783             :         isl_space *space;
     784             :         isl_map *cond;
     785             :         isl_pw_aff *pwaff;
     786             :         struct isl_token *tok;
     787           0 :         int line = -1, col = -1;
     788             :         int is_comp;
     789             : 
     790           0 :         set_current_line_col(s, &line, &col);
     791             : 
     792           0 :         pwaff = accept_affine(s, dim, v);
     793           0 :         if (rational)
     794           0 :                 pwaff = isl_pw_aff_set_rational(pwaff);
     795           0 :         if (!pwaff)
     796           0 :                 return NULL;
     797             : 
     798           0 :         tok = isl_stream_next_token(s);
     799           0 :         if (!tok)
     800           0 :                 return isl_pw_aff_free(pwaff);
     801             : 
     802           0 :         is_comp = is_comparator(tok);
     803           0 :         isl_stream_push_token(s, tok);
     804           0 :         if (!is_comp)
     805           0 :                 return pwaff;
     806             : 
     807           0 :         space = isl_pw_aff_get_domain_space(pwaff);
     808           0 :         cond = isl_map_universe(isl_space_unwrap(space));
     809             : 
     810           0 :         if (push_aff(s, line, col, pwaff) < 0)
     811           0 :                 cond = isl_map_free(cond);
     812           0 :         if (!cond)
     813           0 :                 return NULL;
     814             : 
     815           0 :         cond = read_formula(s, v, cond, rational);
     816             : 
     817           0 :         return accept_ternary(s, cond, v, rational);
     818             : }
     819             : 
     820           0 : static __isl_give isl_map *read_var_def(__isl_keep isl_stream *s,
     821             :         __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
     822             :         int rational)
     823             : {
     824             :         isl_pw_aff *def;
     825             :         int pos;
     826             :         isl_map *def_map;
     827             : 
     828           0 :         if (type == isl_dim_param)
     829           0 :                 pos = isl_map_dim(map, isl_dim_param);
     830             :         else {
     831           0 :                 pos = isl_map_dim(map, isl_dim_in);
     832           0 :                 if (type == isl_dim_out)
     833           0 :                         pos += isl_map_dim(map, isl_dim_out);
     834           0 :                 type = isl_dim_in;
     835             :         }
     836           0 :         --pos;
     837             : 
     838           0 :         def = accept_extended_affine(s, isl_space_wrap(isl_map_get_space(map)),
     839             :                                         v, rational);
     840           0 :         def_map = isl_map_from_pw_aff(def);
     841           0 :         def_map = isl_map_equate(def_map, type, pos, isl_dim_out, 0);
     842           0 :         def_map = isl_set_unwrap(isl_map_domain(def_map));
     843             : 
     844           0 :         map = isl_map_intersect(map, def_map);
     845             : 
     846           0 :         return map;
     847             : }
     848             : 
     849           0 : static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s,
     850             :         __isl_take isl_space *dim, struct vars *v)
     851             : {
     852             :         isl_pw_aff *pwaff;
     853             :         isl_pw_aff_list *list;
     854           0 :         struct isl_token *tok = NULL;
     855             : 
     856           0 :         pwaff = accept_affine(s, isl_space_copy(dim), v);
     857           0 :         list = isl_pw_aff_list_from_pw_aff(pwaff);
     858           0 :         if (!list)
     859           0 :                 goto error;
     860             : 
     861             :         for (;;) {
     862           0 :                 tok = isl_stream_next_token(s);
     863           0 :                 if (!tok) {
     864           0 :                         isl_stream_error(s, NULL, "unexpected EOF");
     865           0 :                         goto error;
     866             :                 }
     867           0 :                 if (tok->type != ',') {
     868           0 :                         isl_stream_push_token(s, tok);
     869           0 :                         break;
     870             :                 }
     871           0 :                 isl_token_free(tok);
     872             : 
     873           0 :                 pwaff = accept_affine(s, isl_space_copy(dim), v);
     874           0 :                 list = isl_pw_aff_list_concat(list,
     875             :                                 isl_pw_aff_list_from_pw_aff(pwaff));
     876           0 :                 if (!list)
     877           0 :                         goto error;
     878           0 :         }
     879             : 
     880           0 :         isl_space_free(dim);
     881           0 :         return list;
     882             : error:
     883           0 :         isl_space_free(dim);
     884           0 :         isl_pw_aff_list_free(list);
     885           0 :         return NULL;
     886             : }
     887             : 
     888           0 : static __isl_give isl_map *read_defined_var_list(__isl_keep isl_stream *s,
     889             :         struct vars *v, __isl_take isl_map *map, int rational)
     890             : {
     891             :         struct isl_token *tok;
     892             : 
     893           0 :         while ((tok = isl_stream_next_token(s)) != NULL) {
     894             :                 int p;
     895           0 :                 int n = v->n;
     896             : 
     897           0 :                 if (tok->type != ISL_TOKEN_IDENT)
     898           0 :                         break;
     899             : 
     900           0 :                 p = vars_pos(v, tok->u.s, -1);
     901           0 :                 if (p < 0)
     902           0 :                         goto error;
     903           0 :                 if (p < n) {
     904           0 :                         isl_stream_error(s, tok, "expecting unique identifier");
     905           0 :                         goto error;
     906             :                 }
     907             : 
     908           0 :                 map = isl_map_add_dims(map, isl_dim_out, 1);
     909             : 
     910           0 :                 isl_token_free(tok);
     911           0 :                 tok = isl_stream_next_token(s);
     912           0 :                 if (tok && tok->type == '=') {
     913           0 :                         isl_token_free(tok);
     914           0 :                         map = read_var_def(s, map, isl_dim_out, v, rational);
     915           0 :                         tok = isl_stream_next_token(s);
     916             :                 }
     917             : 
     918           0 :                 if (!tok || tok->type != ',')
     919             :                         break;
     920             : 
     921           0 :                 isl_token_free(tok);
     922             :         }
     923           0 :         if (tok)
     924           0 :                 isl_stream_push_token(s, tok);
     925             : 
     926           0 :         return map;
     927             : error:
     928           0 :         isl_token_free(tok);
     929           0 :         isl_map_free(map);
     930           0 :         return NULL;
     931             : }
     932             : 
     933           0 : static int next_is_tuple(__isl_keep isl_stream *s)
     934             : {
     935             :         struct isl_token *tok;
     936             :         int is_tuple;
     937             : 
     938           0 :         tok = isl_stream_next_token(s);
     939           0 :         if (!tok)
     940           0 :                 return 0;
     941           0 :         if (tok->type == '[') {
     942           0 :                 isl_stream_push_token(s, tok);
     943           0 :                 return 1;
     944             :         }
     945           0 :         if (tok->type != ISL_TOKEN_IDENT && !tok->is_keyword) {
     946           0 :                 isl_stream_push_token(s, tok);
     947           0 :                 return 0;
     948             :         }
     949             : 
     950           0 :         is_tuple = isl_stream_next_token_is(s, '[');
     951             : 
     952           0 :         isl_stream_push_token(s, tok);
     953             : 
     954           0 :         return is_tuple;
     955             : }
     956             : 
     957             : /* Is "pa" an expression in term of earlier dimensions?
     958             :  * The alternative is that the dimension is defined to be equal to itself,
     959             :  * meaning that it has a universe domain and an expression that depends
     960             :  * on itself.  "i" is the position of the expression in a sequence
     961             :  * of "n" expressions.  The final dimensions of "pa" correspond to
     962             :  * these "n" expressions.
     963             :  */
     964           0 : static int pw_aff_is_expr(__isl_keep isl_pw_aff *pa, int i, int n)
     965             : {
     966             :         isl_aff *aff;
     967             : 
     968           0 :         if (!pa)
     969           0 :                 return -1;
     970           0 :         if (pa->n != 1)
     971           0 :                 return 1;
     972           0 :         if (!isl_set_plain_is_universe(pa->p[0].set))
     973           0 :                 return 1;
     974             : 
     975           0 :         aff = pa->p[0].aff;
     976           0 :         if (isl_int_is_zero(aff->v->el[aff->v->size - n + i]))
     977           0 :                 return 1;
     978           0 :         return 0;
     979             : }
     980             : 
     981             : /* Does the tuple contain any dimensions that are defined
     982             :  * in terms of earlier dimensions?
     983             :  */
     984           0 : static int tuple_has_expr(__isl_keep isl_multi_pw_aff *tuple)
     985             : {
     986             :         int i, n;
     987           0 :         int has_expr = 0;
     988             :         isl_pw_aff *pa;
     989             : 
     990           0 :         if (!tuple)
     991           0 :                 return -1;
     992           0 :         n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
     993           0 :         for (i = 0; i < n; ++i) {
     994           0 :                 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
     995           0 :                 has_expr = pw_aff_is_expr(pa, i, n);
     996           0 :                 isl_pw_aff_free(pa);
     997           0 :                 if (has_expr < 0 || has_expr)
     998             :                         break;
     999             :         }
    1000             : 
    1001           0 :         return has_expr;
    1002             : }
    1003             : 
    1004             : /* Set the name of dimension "pos" in "space" to "name".
    1005             :  * During printing, we add primes if the same name appears more than once
    1006             :  * to distinguish the occurrences.  Here, we remove those primes from "name"
    1007             :  * before setting the name of the dimension.
    1008             :  */
    1009           0 : static __isl_give isl_space *space_set_dim_name(__isl_take isl_space *space,
    1010             :         int pos, char *name)
    1011             : {
    1012             :         char *prime;
    1013             : 
    1014           0 :         if (!name)
    1015           0 :                 return space;
    1016             : 
    1017           0 :         prime = strchr(name, '\'');
    1018           0 :         if (prime)
    1019           0 :                 *prime = '\0';
    1020           0 :         space = isl_space_set_dim_name(space, isl_dim_out, pos, name);
    1021           0 :         if (prime)
    1022           0 :                 *prime = '\'';
    1023             : 
    1024           0 :         return space;
    1025             : }
    1026             : 
    1027             : /* Accept a piecewise affine expression.
    1028             :  *
    1029             :  * At the outer level, the piecewise affine expression may be of the form
    1030             :  *
    1031             :  *      aff1 : condition1; aff2 : conditions2; ...
    1032             :  *
    1033             :  * or simply
    1034             :  *
    1035             :  *      aff
    1036             :  *
    1037             :  * each of the affine expressions may in turn include ternary operators.
    1038             :  *
    1039             :  * There may be parentheses around some subexpression of "aff1"
    1040             :  * around "aff1" itself, around "aff1 : condition1" and/or
    1041             :  * around the entire piecewise affine expression.
    1042             :  * We therefore remove the opening parenthesis (if any) from the stream
    1043             :  * in case the closing parenthesis follows the colon, but if the closing
    1044             :  * parenthesis is the first thing in the stream after the parsed affine
    1045             :  * expression, we push the parsed expression onto the stream and parse
    1046             :  * again in case the parentheses enclose some subexpression of "aff1".
    1047             :  */
    1048           0 : static __isl_give isl_pw_aff *accept_piecewise_affine(__isl_keep isl_stream *s,
    1049             :         __isl_take isl_space *space, struct vars *v, int rational)
    1050             : {
    1051             :         isl_pw_aff *res;
    1052             :         isl_space *res_space;
    1053             : 
    1054           0 :         res_space = isl_space_from_domain(isl_space_copy(space));
    1055           0 :         res_space = isl_space_add_dims(res_space, isl_dim_out, 1);
    1056           0 :         res = isl_pw_aff_empty(res_space);
    1057             :         do {
    1058             :                 isl_pw_aff *pa;
    1059             :                 int seen_paren;
    1060           0 :                 int line = -1, col = -1;
    1061             : 
    1062           0 :                 set_current_line_col(s, &line, &col);
    1063           0 :                 seen_paren = isl_stream_eat_if_available(s, '(');
    1064           0 :                 if (seen_paren)
    1065           0 :                         pa = accept_piecewise_affine(s, isl_space_copy(space),
    1066             :                                                         v, rational);
    1067             :                 else
    1068           0 :                         pa = accept_extended_affine(s, isl_space_copy(space),
    1069             :                                                         v, rational);
    1070           0 :                 if (seen_paren && isl_stream_eat_if_available(s, ')')) {
    1071           0 :                         seen_paren = 0;
    1072           0 :                         if (push_aff(s, line, col, pa) < 0)
    1073           0 :                                 goto error;
    1074           0 :                         pa = accept_extended_affine(s, isl_space_copy(space),
    1075             :                                                         v, rational);
    1076             :                 }
    1077           0 :                 if (isl_stream_eat_if_available(s, ':')) {
    1078             :                         isl_space *dom_space;
    1079             :                         isl_set *dom;
    1080             : 
    1081           0 :                         dom_space = isl_pw_aff_get_domain_space(pa);
    1082           0 :                         dom = isl_set_universe(dom_space);
    1083           0 :                         dom = read_formula(s, v, dom, rational);
    1084           0 :                         pa = isl_pw_aff_intersect_domain(pa, dom);
    1085             :                 }
    1086             : 
    1087           0 :                 res = isl_pw_aff_union_add(res, pa);
    1088             : 
    1089           0 :                 if (seen_paren && isl_stream_eat(s, ')'))
    1090           0 :                         goto error;
    1091           0 :         } while (isl_stream_eat_if_available(s, ';'));
    1092             : 
    1093           0 :         isl_space_free(space);
    1094             : 
    1095           0 :         return res;
    1096             : error:
    1097           0 :         isl_space_free(space);
    1098           0 :         return isl_pw_aff_free(res);
    1099             : }
    1100             : 
    1101             : /* Read an affine expression from "s" for use in read_tuple.
    1102             :  *
    1103             :  * accept_extended_affine requires a wrapped space as input.
    1104             :  * read_tuple on the other hand expects each isl_pw_aff
    1105             :  * to have an anonymous space.  We therefore adjust the space
    1106             :  * of the isl_pw_aff before returning it.
    1107             :  */
    1108           0 : static __isl_give isl_pw_aff *read_tuple_var_def(__isl_keep isl_stream *s,
    1109             :         struct vars *v, int rational)
    1110             : {
    1111             :         isl_space *space;
    1112             :         isl_pw_aff *def;
    1113             : 
    1114           0 :         space = isl_space_wrap(isl_space_alloc(s->ctx, 0, v->n, 0));
    1115             : 
    1116           0 :         def = accept_piecewise_affine(s, space, v, rational);
    1117             : 
    1118           0 :         space = isl_space_set_alloc(s->ctx, 0, v->n);
    1119           0 :         def = isl_pw_aff_reset_domain_space(def, space);
    1120             : 
    1121           0 :         return def;
    1122             : }
    1123             : 
    1124             : /* Read a list of tuple elements by calling "read_el" on each of them and
    1125             :  * return a space with the same number of set dimensions derived from
    1126             :  * the parameter space "space" and possibly updated by "read_el".
    1127             :  * The elements in the list are separated by either "," or "][".
    1128             :  * If "comma" is set then only "," is allowed.
    1129             :  */
    1130           0 : static __isl_give isl_space *read_tuple_list(__isl_keep isl_stream *s,
    1131             :         struct vars *v, __isl_take isl_space *space, int rational, int comma,
    1132             :         __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s,
    1133             :                 struct vars *v, __isl_take isl_space *space, int rational,
    1134             :                 void *user),
    1135             :         void *user)
    1136             : {
    1137           0 :         if (!space)
    1138           0 :                 return NULL;
    1139             : 
    1140           0 :         space = isl_space_set_from_params(space);
    1141             : 
    1142           0 :         if (isl_stream_next_token_is(s, ']'))
    1143           0 :                 return space;
    1144             : 
    1145             :         for (;;) {
    1146             :                 struct isl_token *tok;
    1147             : 
    1148           0 :                 space = isl_space_add_dims(space, isl_dim_set, 1);
    1149             : 
    1150           0 :                 space = read_el(s, v, space, rational, user);
    1151           0 :                 if (!space)
    1152           0 :                         return NULL;
    1153             : 
    1154           0 :                 tok = isl_stream_next_token(s);
    1155           0 :                 if (!comma && tok && tok->type == ']' &&
    1156           0 :                     isl_stream_next_token_is(s, '[')) {
    1157           0 :                         isl_token_free(tok);
    1158           0 :                         tok = isl_stream_next_token(s);
    1159           0 :                 } else if (!tok || tok->type != ',') {
    1160           0 :                         if (tok)
    1161           0 :                                 isl_stream_push_token(s, tok);
    1162           0 :                         break;
    1163             :                 }
    1164             : 
    1165           0 :                 isl_token_free(tok);
    1166           0 :         }
    1167             : 
    1168           0 :         return space;
    1169             : }
    1170             : 
    1171             : /* Read a tuple space from "s" derived from the parameter space "space".
    1172             :  * Call "read_el" on each element in the tuples.
    1173             :  */
    1174           0 : static __isl_give isl_space *read_tuple_space(__isl_keep isl_stream *s,
    1175             :         struct vars *v, __isl_take isl_space *space, int rational, int comma,
    1176             :         __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s,
    1177             :                 struct vars *v, __isl_take isl_space *space, int rational,
    1178             :                 void *user),
    1179             :         void *user)
    1180             : {
    1181             :         struct isl_token *tok;
    1182           0 :         char *name = NULL;
    1183           0 :         isl_space *res = NULL;
    1184             : 
    1185           0 :         tok = isl_stream_next_token(s);
    1186           0 :         if (!tok)
    1187           0 :                 goto error;
    1188           0 :         if (tok->type == ISL_TOKEN_IDENT || tok->is_keyword) {
    1189           0 :                 name = strdup(tok->u.s);
    1190           0 :                 isl_token_free(tok);
    1191           0 :                 if (!name)
    1192           0 :                         goto error;
    1193             :         } else
    1194           0 :                 isl_stream_push_token(s, tok);
    1195           0 :         if (isl_stream_eat(s, '['))
    1196           0 :                 goto error;
    1197           0 :         if (next_is_tuple(s)) {
    1198             :                 isl_space *out;
    1199           0 :                 res = read_tuple_space(s, v, isl_space_copy(space),
    1200             :                                         rational, comma, read_el, user);
    1201           0 :                 if (isl_stream_eat(s, ISL_TOKEN_TO))
    1202           0 :                         goto error;
    1203           0 :                 out = read_tuple_space(s, v, isl_space_copy(space),
    1204             :                                         rational, comma, read_el, user);
    1205           0 :                 res = isl_space_product(res, out);
    1206             :         } else
    1207           0 :                 res = read_tuple_list(s, v, isl_space_copy(space),
    1208             :                                         rational, comma, read_el, user);
    1209           0 :         if (isl_stream_eat(s, ']'))
    1210           0 :                 goto error;
    1211             : 
    1212           0 :         if (name) {
    1213           0 :                 res = isl_space_set_tuple_name(res, isl_dim_set, name);
    1214           0 :                 free(name);
    1215             :         }
    1216             : 
    1217           0 :         isl_space_free(space);
    1218           0 :         return res;
    1219             : error:
    1220           0 :         free(name);
    1221           0 :         isl_space_free(res);
    1222           0 :         isl_space_free(space);
    1223           0 :         return NULL;
    1224             : }
    1225             : 
    1226             : /* Construct an isl_pw_aff defined on a space with v->n variables
    1227             :  * that is equal to the last of those variables.
    1228             :  */
    1229           0 : static __isl_give isl_pw_aff *identity_tuple_el(struct vars *v)
    1230             : {
    1231             :         isl_space *space;
    1232             :         isl_aff *aff;
    1233             : 
    1234           0 :         space = isl_space_set_alloc(v->ctx, 0, v->n);
    1235           0 :         aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
    1236           0 :         aff = isl_aff_add_coefficient_si(aff, isl_dim_in, v->n - 1, 1);
    1237           0 :         return isl_pw_aff_from_aff(aff);
    1238             : }
    1239             : 
    1240             : /* This function is called for each element in a tuple inside read_tuple.
    1241             :  * Add a new variable to "v" and construct a corresponding isl_pw_aff defined
    1242             :  * over a space containing all variables in "v" defined so far.
    1243             :  * The isl_pw_aff expresses the new variable in terms of earlier variables
    1244             :  * if a definition is provided.  Otherwise, it is represented as being
    1245             :  * equal to itself.
    1246             :  * Add the isl_pw_aff to *list.
    1247             :  * If the new variable was named, then adjust "space" accordingly and
    1248             :  * return the updated space.
    1249             :  */
    1250           0 : static __isl_give isl_space *read_tuple_pw_aff_el(__isl_keep isl_stream *s,
    1251             :         struct vars *v, __isl_take isl_space *space, int rational, void *user)
    1252             : {
    1253           0 :         isl_pw_aff_list **list = (isl_pw_aff_list **) user;
    1254             :         isl_pw_aff *pa;
    1255             :         struct isl_token *tok;
    1256           0 :         int new_name = 0;
    1257             : 
    1258           0 :         tok = next_token(s);
    1259           0 :         if (!tok) {
    1260           0 :                 isl_stream_error(s, NULL, "unexpected EOF");
    1261           0 :                 return isl_space_free(space);
    1262             :         }
    1263             : 
    1264           0 :         if (tok->type == ISL_TOKEN_IDENT) {
    1265           0 :                 int n = v->n;
    1266           0 :                 int p = vars_pos(v, tok->u.s, -1);
    1267           0 :                 if (p < 0)
    1268           0 :                         goto error;
    1269           0 :                 new_name = p >= n;
    1270             :         }
    1271             : 
    1272           0 :         if (tok->type == '*') {
    1273           0 :                 if (vars_add_anon(v) < 0)
    1274           0 :                         goto error;
    1275           0 :                 isl_token_free(tok);
    1276           0 :                 pa = identity_tuple_el(v);
    1277           0 :         } else if (new_name) {
    1278           0 :                 int pos = isl_space_dim(space, isl_dim_out) - 1;
    1279           0 :                 space = space_set_dim_name(space, pos, v->v->name);
    1280           0 :                 isl_token_free(tok);
    1281           0 :                 if (isl_stream_eat_if_available(s, '='))
    1282           0 :                         pa = read_tuple_var_def(s, v, rational);
    1283             :                 else
    1284           0 :                         pa = identity_tuple_el(v);
    1285             :         } else {
    1286           0 :                 isl_stream_push_token(s, tok);
    1287           0 :                 tok = NULL;
    1288           0 :                 if (vars_add_anon(v) < 0)
    1289           0 :                         goto error;
    1290           0 :                 pa = read_tuple_var_def(s, v, rational);
    1291             :         }
    1292             : 
    1293           0 :         *list = isl_pw_aff_list_add(*list, pa);
    1294           0 :         if (!*list)
    1295           0 :                 return isl_space_free(space);
    1296             : 
    1297           0 :         return space;
    1298             : error:
    1299           0 :         isl_token_free(tok);
    1300           0 :         return isl_space_free(space);
    1301             : }
    1302             : 
    1303             : /* Read a tuple and represent it as an isl_multi_pw_aff.
    1304             :  * The range space of the isl_multi_pw_aff is the space of the tuple.
    1305             :  * The domain space is an anonymous space
    1306             :  * with a dimension for each variable in the set of variables in "v",
    1307             :  * including the variables in the range.
    1308             :  * If a given dimension is not defined in terms of earlier dimensions in
    1309             :  * the input, then the corresponding isl_pw_aff is set equal to one time
    1310             :  * the variable corresponding to the dimension being defined.
    1311             :  *
    1312             :  * The elements in the tuple are collected in a list by read_tuple_pw_aff_el.
    1313             :  * Each element in this list is defined over a space representing
    1314             :  * the variables defined so far.  We need to adjust the earlier
    1315             :  * elements to have as many variables in the domain as the final
    1316             :  * element in the list.
    1317             :  */
    1318           0 : static __isl_give isl_multi_pw_aff *read_tuple(__isl_keep isl_stream *s,
    1319             :         struct vars *v, int rational, int comma)
    1320             : {
    1321             :         int i, n;
    1322             :         isl_space *space;
    1323             :         isl_pw_aff_list *list;
    1324             : 
    1325           0 :         space = isl_space_params_alloc(v->ctx, 0);
    1326           0 :         list = isl_pw_aff_list_alloc(s->ctx, 0);
    1327           0 :         space = read_tuple_space(s, v, space, rational, comma,
    1328             :                                 &read_tuple_pw_aff_el, &list);
    1329           0 :         n = isl_space_dim(space, isl_dim_set);
    1330           0 :         for (i = 0; i + 1 < n; ++i) {
    1331             :                 isl_pw_aff *pa;
    1332             : 
    1333           0 :                 pa = isl_pw_aff_list_get_pw_aff(list, i);
    1334           0 :                 pa = isl_pw_aff_add_dims(pa, isl_dim_in, n - (i + 1));
    1335           0 :                 list = isl_pw_aff_list_set_pw_aff(list, i, pa);
    1336             :         }
    1337             : 
    1338           0 :         space = isl_space_from_range(space);
    1339           0 :         space = isl_space_add_dims(space, isl_dim_in, v->n);
    1340           0 :         return isl_multi_pw_aff_from_pw_aff_list(space, list);
    1341             : }
    1342             : 
    1343             : /* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map".
    1344             :  * We first create the appropriate space in "map" based on the range
    1345             :  * space of this isl_multi_pw_aff.  Then, we add equalities based
    1346             :  * on the affine expressions.  These live in an anonymous space,
    1347             :  * however, so we first need to reset the space to that of "map".
    1348             :  */
    1349           0 : static __isl_give isl_map *map_from_tuple(__isl_take isl_multi_pw_aff *tuple,
    1350             :         __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
    1351             :         int rational)
    1352             : {
    1353             :         int i, n;
    1354             :         isl_ctx *ctx;
    1355           0 :         isl_space *space = NULL;
    1356             : 
    1357           0 :         if (!map || !tuple)
    1358             :                 goto error;
    1359           0 :         ctx = isl_multi_pw_aff_get_ctx(tuple);
    1360           0 :         n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
    1361           0 :         space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
    1362           0 :         if (!space)
    1363           0 :                 goto error;
    1364             : 
    1365           0 :         if (type == isl_dim_param) {
    1366           0 :                 if (isl_space_has_tuple_name(space, isl_dim_set) ||
    1367           0 :                     isl_space_is_wrapping(space)) {
    1368           0 :                         isl_die(ctx, isl_error_invalid,
    1369             :                                 "parameter tuples cannot be named or nested",
    1370             :                                 goto error);
    1371             :                 }
    1372           0 :                 map = isl_map_add_dims(map, type, n);
    1373           0 :                 for (i = 0; i < n; ++i) {
    1374             :                         isl_id *id;
    1375           0 :                         if (!isl_space_has_dim_name(space, isl_dim_set, i))
    1376           0 :                                 isl_die(ctx, isl_error_invalid,
    1377             :                                         "parameters must be named",
    1378             :                                         goto error);
    1379           0 :                         id = isl_space_get_dim_id(space, isl_dim_set, i);
    1380           0 :                         map = isl_map_set_dim_id(map, isl_dim_param, i, id);
    1381             :                 }
    1382           0 :         } else if (type == isl_dim_in) {
    1383             :                 isl_set *set;
    1384             : 
    1385           0 :                 set = isl_set_universe(isl_space_copy(space));
    1386           0 :                 if (rational)
    1387           0 :                         set = isl_set_set_rational(set);
    1388           0 :                 set = isl_set_intersect_params(set, isl_map_params(map));
    1389           0 :                 map = isl_map_from_domain(set);
    1390             :         } else {
    1391             :                 isl_set *set;
    1392             : 
    1393           0 :                 set = isl_set_universe(isl_space_copy(space));
    1394           0 :                 if (rational)
    1395           0 :                         set = isl_set_set_rational(set);
    1396           0 :                 map = isl_map_from_domain_and_range(isl_map_domain(map), set);
    1397             :         }
    1398             : 
    1399           0 :         for (i = 0; i < n; ++i) {
    1400             :                 isl_pw_aff *pa;
    1401             :                 isl_space *space;
    1402             :                 isl_aff *aff;
    1403             :                 isl_set *set;
    1404             :                 isl_map *map_i;
    1405             : 
    1406           0 :                 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
    1407           0 :                 space = isl_pw_aff_get_domain_space(pa);
    1408           0 :                 aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
    1409           0 :                 aff = isl_aff_add_coefficient_si(aff,
    1410           0 :                                                 isl_dim_in, v->n - n + i, -1);
    1411           0 :                 pa = isl_pw_aff_add(pa, isl_pw_aff_from_aff(aff));
    1412           0 :                 if (rational)
    1413           0 :                         pa = isl_pw_aff_set_rational(pa);
    1414           0 :                 set = isl_pw_aff_zero_set(pa);
    1415           0 :                 map_i = isl_map_from_range(set);
    1416           0 :                 map_i = isl_map_reset_space(map_i, isl_map_get_space(map));
    1417           0 :                 map = isl_map_intersect(map, map_i);
    1418             :         }
    1419             : 
    1420           0 :         isl_space_free(space);
    1421           0 :         isl_multi_pw_aff_free(tuple);
    1422           0 :         return map;
    1423             : error:
    1424           0 :         isl_space_free(space);
    1425           0 :         isl_multi_pw_aff_free(tuple);
    1426           0 :         isl_map_free(map);
    1427           0 :         return NULL;
    1428             : }
    1429             : 
    1430             : /* Read a tuple from "s" and add it to "map".
    1431             :  * The tuple is initially represented as an isl_multi_pw_aff and
    1432             :  * then added to "map".
    1433             :  */
    1434           0 : static __isl_give isl_map *read_map_tuple(__isl_keep isl_stream *s,
    1435             :         __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
    1436             :         int rational, int comma)
    1437             : {
    1438             :         isl_multi_pw_aff *tuple;
    1439             : 
    1440           0 :         tuple = read_tuple(s, v, rational, comma);
    1441           0 :         if (!tuple)
    1442           0 :                 return isl_map_free(map);
    1443             : 
    1444           0 :         return map_from_tuple(tuple, map, type, v, rational);
    1445             : }
    1446             : 
    1447             : /* Given two equal-length lists of piecewise affine expression with the space
    1448             :  * of "set" as domain, construct a set in the same space that expresses
    1449             :  * that "left" and "right" satisfy the comparison "type".
    1450             :  *
    1451             :  * A space is constructed of the same dimension as the number of elements
    1452             :  * in the two lists.  The comparison is then expressed in a map from
    1453             :  * this space to itself and wrapped into a set.  Finally the two lists
    1454             :  * of piecewise affine expressions are plugged into this set.
    1455             :  *
    1456             :  * Let S be the space of "set" and T the constructed space.
    1457             :  * The lists are first changed into two isl_multi_pw_affs in S -> T and
    1458             :  * then combined into an isl_multi_pw_aff in S -> [T -> T],
    1459             :  * while the comparison is first expressed in T -> T, then [T -> T]
    1460             :  * and finally in S.
    1461             :  */
    1462           0 : static __isl_give isl_set *list_cmp(__isl_keep isl_set *set, int type,
    1463             :         __isl_take isl_pw_aff_list *left, __isl_take isl_pw_aff_list *right)
    1464             : {
    1465             :         isl_space *space;
    1466             :         int n;
    1467             :         isl_multi_pw_aff *mpa1, *mpa2;
    1468             : 
    1469           0 :         if (!set || !left || !right)
    1470             :                 goto error;
    1471             : 
    1472           0 :         space = isl_set_get_space(set);
    1473           0 :         n = isl_pw_aff_list_n_pw_aff(left);
    1474           0 :         space = isl_space_from_domain(space);
    1475           0 :         space = isl_space_add_dims(space, isl_dim_out, n);
    1476           0 :         mpa1 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), left);
    1477           0 :         mpa2 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), right);
    1478           0 :         mpa1 = isl_multi_pw_aff_range_product(mpa1, mpa2);
    1479             : 
    1480           0 :         space = isl_space_range(space);
    1481           0 :         switch (type) {
    1482             :         case ISL_TOKEN_LEX_LT:
    1483           0 :                 set = isl_map_wrap(isl_map_lex_lt(space));
    1484           0 :                 break;
    1485             :         case ISL_TOKEN_LEX_GT:
    1486           0 :                 set = isl_map_wrap(isl_map_lex_gt(space));
    1487           0 :                 break;
    1488             :         case ISL_TOKEN_LEX_LE:
    1489           0 :                 set = isl_map_wrap(isl_map_lex_le(space));
    1490           0 :                 break;
    1491             :         case ISL_TOKEN_LEX_GE:
    1492           0 :                 set = isl_map_wrap(isl_map_lex_ge(space));
    1493           0 :                 break;
    1494             :         default:
    1495           0 :                 isl_multi_pw_aff_free(mpa1);
    1496           0 :                 isl_space_free(space);
    1497           0 :                 isl_die(isl_set_get_ctx(set), isl_error_internal,
    1498             :                         "unhandled list comparison type", return NULL);
    1499             :         }
    1500           0 :         set = isl_set_preimage_multi_pw_aff(set, mpa1);
    1501           0 :         return set;
    1502             : error:
    1503           0 :         isl_pw_aff_list_free(left);
    1504           0 :         isl_pw_aff_list_free(right);
    1505           0 :         return NULL;
    1506             : }
    1507             : 
    1508             : /* Construct constraints of the form
    1509             :  *
    1510             :  *      a op b
    1511             :  *
    1512             :  * where a is an element in "left", op is an operator of type "type" and
    1513             :  * b is an element in "right", add the constraints to "set" and return
    1514             :  * the result.
    1515             :  * "rational" is set if the constraints should be treated as
    1516             :  * a rational constraints.
    1517             :  *
    1518             :  * If "type" is the type of a comparison operator between lists
    1519             :  * of affine expressions, then a single (compound) constraint
    1520             :  * is constructed by list_cmp instead.
    1521             :  */
    1522           0 : static __isl_give isl_set *construct_constraints(
    1523             :         __isl_take isl_set *set, int type,
    1524             :         __isl_keep isl_pw_aff_list *left, __isl_keep isl_pw_aff_list *right,
    1525             :         int rational)
    1526             : {
    1527             :         isl_set *cond;
    1528             : 
    1529           0 :         left = isl_pw_aff_list_copy(left);
    1530           0 :         right = isl_pw_aff_list_copy(right);
    1531           0 :         if (rational) {
    1532           0 :                 left = isl_pw_aff_list_set_rational(left);
    1533           0 :                 right = isl_pw_aff_list_set_rational(right);
    1534             :         }
    1535           0 :         if (is_list_comparator_type(type))
    1536           0 :                 cond = list_cmp(set, type, left, right);
    1537           0 :         else if (type == ISL_TOKEN_LE)
    1538           0 :                 cond = isl_pw_aff_list_le_set(left, right);
    1539           0 :         else if (type == ISL_TOKEN_GE)
    1540           0 :                 cond = isl_pw_aff_list_ge_set(left, right);
    1541           0 :         else if (type == ISL_TOKEN_LT)
    1542           0 :                 cond = isl_pw_aff_list_lt_set(left, right);
    1543           0 :         else if (type == ISL_TOKEN_GT)
    1544           0 :                 cond = isl_pw_aff_list_gt_set(left, right);
    1545           0 :         else if (type == ISL_TOKEN_NE)
    1546           0 :                 cond = isl_pw_aff_list_ne_set(left, right);
    1547             :         else
    1548           0 :                 cond = isl_pw_aff_list_eq_set(left, right);
    1549             : 
    1550           0 :         return isl_set_intersect(set, cond);
    1551             : }
    1552             : 
    1553             : /* Read a constraint from "s", add it to "map" and return the result.
    1554             :  * "v" contains a description of the identifiers parsed so far.
    1555             :  * "rational" is set if the constraint should be treated as
    1556             :  * a rational constraint.
    1557             :  * The constraint read from "s" may be applied to multiple pairs
    1558             :  * of affine expressions and may be chained.
    1559             :  * In particular, a list of affine expressions is read, followed
    1560             :  * by a comparison operator and another list of affine expressions.
    1561             :  * The comparison operator is then applied to each pair of elements
    1562             :  * in the two lists and the results are added to "map".
    1563             :  * However, if the operator expects two lists of affine expressions,
    1564             :  * then it is applied directly to those lists and the two lists
    1565             :  * are required to have the same length.
    1566             :  * If the next token is another comparison operator, then another
    1567             :  * list of affine expressions is read and the process repeats.
    1568             :  *
    1569             :  * The processing is performed on a wrapped copy of "map" because
    1570             :  * an affine expression cannot have a binary relation as domain.
    1571             :  */
    1572           0 : static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
    1573             :         struct vars *v, __isl_take isl_map *map, int rational)
    1574             : {
    1575             :         struct isl_token *tok;
    1576             :         int type;
    1577           0 :         isl_pw_aff_list *list1 = NULL, *list2 = NULL;
    1578             :         int n1, n2;
    1579             :         isl_set *set;
    1580             : 
    1581           0 :         set = isl_map_wrap(map);
    1582           0 :         list1 = accept_affine_list(s, isl_set_get_space(set), v);
    1583           0 :         if (!list1)
    1584           0 :                 goto error;
    1585           0 :         tok = isl_stream_next_token(s);
    1586           0 :         if (!is_comparator(tok)) {
    1587           0 :                 isl_stream_error(s, tok, "missing operator");
    1588           0 :                 if (tok)
    1589           0 :                         isl_stream_push_token(s, tok);
    1590           0 :                 goto error;
    1591             :         }
    1592           0 :         type = tok->type;
    1593           0 :         isl_token_free(tok);
    1594             :         for (;;) {
    1595           0 :                 list2 = accept_affine_list(s, isl_set_get_space(set), v);
    1596           0 :                 if (!list2)
    1597           0 :                         goto error;
    1598           0 :                 n1 = isl_pw_aff_list_n_pw_aff(list1);
    1599           0 :                 n2 = isl_pw_aff_list_n_pw_aff(list2);
    1600           0 :                 if (is_list_comparator_type(type) && n1 != n2) {
    1601           0 :                         isl_stream_error(s, NULL,
    1602             :                                         "list arguments not of same size");
    1603           0 :                         goto error;
    1604             :                 }
    1605             : 
    1606           0 :                 set = construct_constraints(set, type, list1, list2, rational);
    1607           0 :                 isl_pw_aff_list_free(list1);
    1608           0 :                 list1 = list2;
    1609             : 
    1610           0 :                 tok = isl_stream_next_token(s);
    1611           0 :                 if (!is_comparator(tok)) {
    1612           0 :                         if (tok)
    1613           0 :                                 isl_stream_push_token(s, tok);
    1614           0 :                         break;
    1615             :                 }
    1616           0 :                 type = tok->type;
    1617           0 :                 isl_token_free(tok);
    1618           0 :         }
    1619           0 :         isl_pw_aff_list_free(list1);
    1620             : 
    1621           0 :         return isl_set_unwrap(set);
    1622             : error:
    1623           0 :         isl_pw_aff_list_free(list1);
    1624           0 :         isl_pw_aff_list_free(list2);
    1625           0 :         isl_set_free(set);
    1626           0 :         return NULL;
    1627             : }
    1628             : 
    1629           0 : static __isl_give isl_map *read_exists(__isl_keep isl_stream *s,
    1630             :         struct vars *v, __isl_take isl_map *map, int rational)
    1631             : {
    1632           0 :         int n = v->n;
    1633           0 :         int seen_paren = isl_stream_eat_if_available(s, '(');
    1634             : 
    1635           0 :         map = isl_map_from_domain(isl_map_wrap(map));
    1636           0 :         map = read_defined_var_list(s, v, map, rational);
    1637             : 
    1638           0 :         if (isl_stream_eat(s, ':'))
    1639           0 :                 goto error;
    1640             : 
    1641           0 :         map = read_formula(s, v, map, rational);
    1642           0 :         map = isl_set_unwrap(isl_map_domain(map));
    1643             : 
    1644           0 :         vars_drop(v, v->n - n);
    1645           0 :         if (seen_paren && isl_stream_eat(s, ')'))
    1646           0 :                 goto error;
    1647             : 
    1648           0 :         return map;
    1649             : error:
    1650           0 :         isl_map_free(map);
    1651           0 :         return NULL;
    1652             : }
    1653             : 
    1654             : /* Parse an expression between parentheses and push the result
    1655             :  * back on the stream.
    1656             :  *
    1657             :  * The parsed expression may be either an affine expression
    1658             :  * or a condition.  The first type is pushed onto the stream
    1659             :  * as an isl_pw_aff, while the second is pushed as an isl_map.
    1660             :  *
    1661             :  * If the initial token indicates the start of a condition,
    1662             :  * we parse it as such.
    1663             :  * Otherwise, we first parse an affine expression and push
    1664             :  * that onto the stream.  If the affine expression covers the
    1665             :  * entire expression between parentheses, we return.
    1666             :  * Otherwise, we assume that the affine expression is the
    1667             :  * start of a condition and continue parsing.
    1668             :  */
    1669           0 : static int resolve_paren_expr(__isl_keep isl_stream *s,
    1670             :         struct vars *v, __isl_take isl_map *map, int rational)
    1671             : {
    1672             :         struct isl_token *tok, *tok2;
    1673             :         int line, col;
    1674             :         isl_pw_aff *pwaff;
    1675             : 
    1676           0 :         tok = isl_stream_next_token(s);
    1677           0 :         if (!tok || tok->type != '(')
    1678             :                 goto error;
    1679             : 
    1680           0 :         if (isl_stream_next_token_is(s, '('))
    1681           0 :                 if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
    1682           0 :                         goto error;
    1683             : 
    1684           0 :         if (isl_stream_next_token_is(s, ISL_TOKEN_EXISTS) ||
    1685           0 :             isl_stream_next_token_is(s, ISL_TOKEN_NOT) ||
    1686           0 :             isl_stream_next_token_is(s, ISL_TOKEN_TRUE) ||
    1687           0 :             isl_stream_next_token_is(s, ISL_TOKEN_FALSE) ||
    1688           0 :             isl_stream_next_token_is(s, ISL_TOKEN_MAP)) {
    1689           0 :                 map = read_formula(s, v, map, rational);
    1690           0 :                 if (isl_stream_eat(s, ')'))
    1691           0 :                         goto error;
    1692           0 :                 tok->type = ISL_TOKEN_MAP;
    1693           0 :                 tok->u.map = map;
    1694           0 :                 isl_stream_push_token(s, tok);
    1695           0 :                 return 0;
    1696             :         }
    1697             : 
    1698           0 :         tok2 = isl_stream_next_token(s);
    1699           0 :         if (!tok2)
    1700           0 :                 goto error;
    1701           0 :         line = tok2->line;
    1702           0 :         col = tok2->col;
    1703           0 :         isl_stream_push_token(s, tok2);
    1704             : 
    1705           0 :         pwaff = accept_affine(s, isl_space_wrap(isl_map_get_space(map)), v);
    1706           0 :         if (!pwaff)
    1707           0 :                 goto error;
    1708             : 
    1709           0 :         tok2 = isl_token_new(s->ctx, line, col, 0);
    1710           0 :         if (!tok2)
    1711           0 :                 goto error2;
    1712           0 :         tok2->type = ISL_TOKEN_AFF;
    1713           0 :         tok2->u.pwaff = pwaff;
    1714             : 
    1715           0 :         if (isl_stream_eat_if_available(s, ')')) {
    1716           0 :                 isl_stream_push_token(s, tok2);
    1717           0 :                 isl_token_free(tok);
    1718           0 :                 isl_map_free(map);
    1719           0 :                 return 0;
    1720             :         }
    1721             : 
    1722           0 :         isl_stream_push_token(s, tok2);
    1723             : 
    1724           0 :         map = read_formula(s, v, map, rational);
    1725           0 :         if (isl_stream_eat(s, ')'))
    1726           0 :                 goto error;
    1727             : 
    1728           0 :         tok->type = ISL_TOKEN_MAP;
    1729           0 :         tok->u.map = map;
    1730           0 :         isl_stream_push_token(s, tok);
    1731             : 
    1732           0 :         return 0;
    1733             : error2:
    1734           0 :         isl_pw_aff_free(pwaff);
    1735             : error:
    1736           0 :         isl_token_free(tok);
    1737           0 :         isl_map_free(map);
    1738           0 :         return -1;
    1739             : }
    1740             : 
    1741           0 : static __isl_give isl_map *read_conjunct(__isl_keep isl_stream *s,
    1742             :         struct vars *v, __isl_take isl_map *map, int rational)
    1743             : {
    1744           0 :         if (isl_stream_next_token_is(s, '('))
    1745           0 :                 if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
    1746           0 :                         goto error;
    1747             : 
    1748           0 :         if (isl_stream_next_token_is(s, ISL_TOKEN_MAP)) {
    1749             :                 struct isl_token *tok;
    1750           0 :                 tok = isl_stream_next_token(s);
    1751           0 :                 if (!tok)
    1752           0 :                         goto error;
    1753           0 :                 isl_map_free(map);
    1754           0 :                 map = isl_map_copy(tok->u.map);
    1755           0 :                 isl_token_free(tok);
    1756           0 :                 return map;
    1757             :         }
    1758             : 
    1759           0 :         if (isl_stream_eat_if_available(s, ISL_TOKEN_EXISTS))
    1760           0 :                 return read_exists(s, v, map, rational);
    1761             : 
    1762           0 :         if (isl_stream_eat_if_available(s, ISL_TOKEN_TRUE))
    1763           0 :                 return map;
    1764             : 
    1765           0 :         if (isl_stream_eat_if_available(s, ISL_TOKEN_FALSE)) {
    1766           0 :                 isl_space *dim = isl_map_get_space(map);
    1767           0 :                 isl_map_free(map);
    1768           0 :                 return isl_map_empty(dim);
    1769             :         }
    1770             :                 
    1771           0 :         return add_constraint(s, v, map, rational);
    1772             : error:
    1773           0 :         isl_map_free(map);
    1774           0 :         return NULL;
    1775             : }
    1776             : 
    1777           0 : static __isl_give isl_map *read_conjuncts(__isl_keep isl_stream *s,
    1778             :         struct vars *v, __isl_take isl_map *map, int rational)
    1779             : {
    1780             :         isl_map *res;
    1781             :         int negate;
    1782             : 
    1783           0 :         negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT);
    1784           0 :         res = read_conjunct(s, v, isl_map_copy(map), rational);
    1785           0 :         if (negate)
    1786           0 :                 res = isl_map_subtract(isl_map_copy(map), res);
    1787             : 
    1788           0 :         while (res && isl_stream_eat_if_available(s, ISL_TOKEN_AND)) {
    1789             :                 isl_map *res_i;
    1790             : 
    1791           0 :                 negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT);
    1792           0 :                 res_i = read_conjunct(s, v, isl_map_copy(map), rational);
    1793           0 :                 if (negate)
    1794           0 :                         res = isl_map_subtract(res, res_i);
    1795             :                 else
    1796           0 :                         res = isl_map_intersect(res, res_i);
    1797             :         }
    1798             : 
    1799           0 :         isl_map_free(map);
    1800           0 :         return res;
    1801             : }
    1802             : 
    1803           0 : static struct isl_map *read_disjuncts(__isl_keep isl_stream *s,
    1804             :         struct vars *v, __isl_take isl_map *map, int rational)
    1805             : {
    1806             :         isl_map *res;
    1807             : 
    1808           0 :         if (isl_stream_next_token_is(s, '}'))
    1809           0 :                 return map;
    1810             : 
    1811           0 :         res = read_conjuncts(s, v, isl_map_copy(map), rational);
    1812           0 :         while (isl_stream_eat_if_available(s, ISL_TOKEN_OR)) {
    1813             :                 isl_map *res_i;
    1814             : 
    1815           0 :                 res_i = read_conjuncts(s, v, isl_map_copy(map), rational);
    1816           0 :                 res = isl_map_union(res, res_i);
    1817             :         }
    1818             : 
    1819           0 :         isl_map_free(map);
    1820           0 :         return res;
    1821             : }
    1822             : 
    1823             : /* Read a first order formula from "s", add the corresponding
    1824             :  * constraints to "map" and return the result.
    1825             :  *
    1826             :  * In particular, read a formula of the form
    1827             :  *
    1828             :  *      a
    1829             :  *
    1830             :  * or
    1831             :  *
    1832             :  *      a implies b
    1833             :  *
    1834             :  * where a and b are disjunctions.
    1835             :  *
    1836             :  * In the first case, map is replaced by
    1837             :  *
    1838             :  *      map \cap { [..] : a }
    1839             :  *
    1840             :  * In the second case, it is replaced by
    1841             :  *
    1842             :  *      (map \setminus { [..] : a}) \cup (map \cap { [..] : b })
    1843             :  */
    1844           0 : static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
    1845             :         struct vars *v, __isl_take isl_map *map, int rational)
    1846             : {
    1847             :         isl_map *res;
    1848             : 
    1849           0 :         res = read_disjuncts(s, v, isl_map_copy(map), rational);
    1850             : 
    1851           0 :         if (isl_stream_eat_if_available(s, ISL_TOKEN_IMPLIES)) {
    1852             :                 isl_map *res2;
    1853             : 
    1854           0 :                 res = isl_map_subtract(isl_map_copy(map), res);
    1855           0 :                 res2 = read_disjuncts(s, v, map, rational);
    1856           0 :                 res = isl_map_union(res, res2);
    1857             :         } else
    1858           0 :                 isl_map_free(map);
    1859             : 
    1860           0 :         return res;
    1861             : }
    1862             : 
    1863           0 : static int polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
    1864             : {
    1865           0 :         if (pos < isl_basic_map_dim(bmap, isl_dim_out))
    1866           0 :                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
    1867           0 :                            isl_basic_map_dim(bmap, isl_dim_in) + pos;
    1868           0 :         pos -= isl_basic_map_dim(bmap, isl_dim_out);
    1869             : 
    1870           0 :         if (pos < isl_basic_map_dim(bmap, isl_dim_in))
    1871           0 :                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) + pos;
    1872           0 :         pos -= isl_basic_map_dim(bmap, isl_dim_in);
    1873             : 
    1874           0 :         if (pos < isl_basic_map_dim(bmap, isl_dim_div))
    1875           0 :                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
    1876           0 :                            isl_basic_map_dim(bmap, isl_dim_in) +
    1877           0 :                            isl_basic_map_dim(bmap, isl_dim_out) + pos;
    1878           0 :         pos -= isl_basic_map_dim(bmap, isl_dim_div);
    1879             : 
    1880           0 :         if (pos < isl_basic_map_dim(bmap, isl_dim_param))
    1881           0 :                 return 1 + pos;
    1882             : 
    1883           0 :         return 0;
    1884             : }
    1885             : 
    1886           0 : static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
    1887             :         __isl_keep isl_stream *s, __isl_take isl_basic_map *bmap)
    1888             : {
    1889             :         int j;
    1890             :         struct isl_token *tok;
    1891             :         int type;
    1892             :         int k;
    1893             :         isl_int *c;
    1894             : 
    1895           0 :         if (!bmap)
    1896           0 :                 return NULL;
    1897             : 
    1898           0 :         tok = isl_stream_next_token(s);
    1899           0 :         if (!tok || tok->type != ISL_TOKEN_VALUE) {
    1900           0 :                 isl_stream_error(s, tok, "expecting coefficient");
    1901           0 :                 if (tok)
    1902           0 :                         isl_stream_push_token(s, tok);
    1903           0 :                 goto error;
    1904             :         }
    1905           0 :         if (!tok->on_new_line) {
    1906           0 :                 isl_stream_error(s, tok, "coefficient should appear on new line");
    1907           0 :                 isl_stream_push_token(s, tok);
    1908           0 :                 goto error;
    1909             :         }
    1910             : 
    1911           0 :         type = isl_int_get_si(tok->u.v);
    1912           0 :         isl_token_free(tok);
    1913             : 
    1914           0 :         isl_assert(s->ctx, type == 0 || type == 1, goto error);
    1915           0 :         if (type == 0) {
    1916           0 :                 k = isl_basic_map_alloc_equality(bmap);
    1917           0 :                 c = bmap->eq[k];
    1918             :         } else {
    1919           0 :                 k = isl_basic_map_alloc_inequality(bmap);
    1920           0 :                 c = bmap->ineq[k];
    1921             :         }
    1922           0 :         if (k < 0)
    1923           0 :                 goto error;
    1924             : 
    1925           0 :         for (j = 0; j < 1 + isl_basic_map_total_dim(bmap); ++j) {
    1926             :                 int pos;
    1927           0 :                 tok = isl_stream_next_token(s);
    1928           0 :                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
    1929           0 :                         isl_stream_error(s, tok, "expecting coefficient");
    1930           0 :                         if (tok)
    1931           0 :                                 isl_stream_push_token(s, tok);
    1932           0 :                         goto error;
    1933             :                 }
    1934           0 :                 if (tok->on_new_line) {
    1935           0 :                         isl_stream_error(s, tok,
    1936             :                                 "coefficient should not appear on new line");
    1937           0 :                         isl_stream_push_token(s, tok);
    1938           0 :                         goto error;
    1939             :                 }
    1940           0 :                 pos = polylib_pos_to_isl_pos(bmap, j);
    1941           0 :                 isl_int_set(c[pos], tok->u.v);
    1942           0 :                 isl_token_free(tok);
    1943             :         }
    1944             : 
    1945           0 :         return bmap;
    1946             : error:
    1947           0 :         isl_basic_map_free(bmap);
    1948           0 :         return NULL;
    1949             : }
    1950             : 
    1951           0 : static __isl_give isl_basic_map *basic_map_read_polylib(
    1952             :         __isl_keep isl_stream *s)
    1953             : {
    1954             :         int i;
    1955             :         struct isl_token *tok;
    1956             :         struct isl_token *tok2;
    1957             :         int n_row, n_col;
    1958             :         int on_new_line;
    1959           0 :         unsigned in = 0, out, local = 0;
    1960           0 :         struct isl_basic_map *bmap = NULL;
    1961           0 :         int nparam = 0;
    1962             : 
    1963           0 :         tok = isl_stream_next_token(s);
    1964           0 :         if (!tok) {
    1965           0 :                 isl_stream_error(s, NULL, "unexpected EOF");
    1966           0 :                 return NULL;
    1967             :         }
    1968           0 :         tok2 = isl_stream_next_token(s);
    1969           0 :         if (!tok2) {
    1970           0 :                 isl_token_free(tok);
    1971           0 :                 isl_stream_error(s, NULL, "unexpected EOF");
    1972           0 :                 return NULL;
    1973             :         }
    1974           0 :         if (tok->type != ISL_TOKEN_VALUE || tok2->type != ISL_TOKEN_VALUE) {
    1975           0 :                 isl_stream_push_token(s, tok2);
    1976           0 :                 isl_stream_push_token(s, tok);
    1977           0 :                 isl_stream_error(s, NULL,
    1978             :                                  "expecting constraint matrix dimensions");
    1979           0 :                 return NULL;
    1980             :         }
    1981           0 :         n_row = isl_int_get_si(tok->u.v);
    1982           0 :         n_col = isl_int_get_si(tok2->u.v);
    1983           0 :         on_new_line = tok2->on_new_line;
    1984           0 :         isl_token_free(tok2);
    1985           0 :         isl_token_free(tok);
    1986           0 :         isl_assert(s->ctx, !on_new_line, return NULL);
    1987           0 :         isl_assert(s->ctx, n_row >= 0, return NULL);
    1988           0 :         isl_assert(s->ctx, n_col >= 2 + nparam, return NULL);
    1989           0 :         tok = isl_stream_next_token_on_same_line(s);
    1990           0 :         if (tok) {
    1991           0 :                 if (tok->type != ISL_TOKEN_VALUE) {
    1992           0 :                         isl_stream_error(s, tok,
    1993             :                                     "expecting number of output dimensions");
    1994           0 :                         isl_stream_push_token(s, tok);
    1995           0 :                         goto error;
    1996             :                 }
    1997           0 :                 out = isl_int_get_si(tok->u.v);
    1998           0 :                 isl_token_free(tok);
    1999             : 
    2000           0 :                 tok = isl_stream_next_token_on_same_line(s);
    2001           0 :                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
    2002           0 :                         isl_stream_error(s, tok,
    2003             :                                     "expecting number of input dimensions");
    2004           0 :                         if (tok)
    2005           0 :                                 isl_stream_push_token(s, tok);
    2006           0 :                         goto error;
    2007             :                 }
    2008           0 :                 in = isl_int_get_si(tok->u.v);
    2009           0 :                 isl_token_free(tok);
    2010             : 
    2011           0 :                 tok = isl_stream_next_token_on_same_line(s);
    2012           0 :                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
    2013           0 :                         isl_stream_error(s, tok,
    2014             :                                     "expecting number of existentials");
    2015           0 :                         if (tok)
    2016           0 :                                 isl_stream_push_token(s, tok);
    2017           0 :                         goto error;
    2018             :                 }
    2019           0 :                 local = isl_int_get_si(tok->u.v);
    2020           0 :                 isl_token_free(tok);
    2021             : 
    2022           0 :                 tok = isl_stream_next_token_on_same_line(s);
    2023           0 :                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
    2024           0 :                         isl_stream_error(s, tok,
    2025             :                                     "expecting number of parameters");
    2026           0 :                         if (tok)
    2027           0 :                                 isl_stream_push_token(s, tok);
    2028           0 :                         goto error;
    2029             :                 }
    2030           0 :                 nparam = isl_int_get_si(tok->u.v);
    2031           0 :                 isl_token_free(tok);
    2032           0 :                 if (n_col != 1 + out + in + local + nparam + 1) {
    2033           0 :                         isl_stream_error(s, NULL,
    2034             :                                     "dimensions don't match");
    2035           0 :                         goto error;
    2036             :                 }
    2037             :         } else
    2038           0 :                 out = n_col - 2 - nparam;
    2039           0 :         bmap = isl_basic_map_alloc(s->ctx, nparam, in, out, local, n_row, n_row);
    2040           0 :         if (!bmap)
    2041           0 :                 return NULL;
    2042             : 
    2043           0 :         for (i = 0; i < local; ++i) {
    2044           0 :                 int k = isl_basic_map_alloc_div(bmap);
    2045           0 :                 if (k < 0)
    2046           0 :                         goto error;
    2047           0 :                 isl_seq_clr(bmap->div[k], 1 + 1 + nparam + in + out + local);
    2048             :         }
    2049             : 
    2050           0 :         for (i = 0; i < n_row; ++i)
    2051           0 :                 bmap = basic_map_read_polylib_constraint(s, bmap);
    2052             : 
    2053           0 :         tok = isl_stream_next_token_on_same_line(s);
    2054           0 :         if (tok) {
    2055           0 :                 isl_stream_error(s, tok, "unexpected extra token on line");
    2056           0 :                 isl_stream_push_token(s, tok);
    2057           0 :                 goto error;
    2058             :         }
    2059             : 
    2060           0 :         bmap = isl_basic_map_simplify(bmap);
    2061           0 :         bmap = isl_basic_map_finalize(bmap);
    2062           0 :         return bmap;
    2063             : error:
    2064           0 :         isl_basic_map_free(bmap);
    2065           0 :         return NULL;
    2066             : }
    2067             : 
    2068           0 : static struct isl_map *map_read_polylib(__isl_keep isl_stream *s)
    2069             : {
    2070             :         struct isl_token *tok;
    2071             :         struct isl_token *tok2;
    2072             :         int i, n;
    2073             :         struct isl_map *map;
    2074             : 
    2075           0 :         tok = isl_stream_next_token(s);
    2076           0 :         if (!tok) {
    2077           0 :                 isl_stream_error(s, NULL, "unexpected EOF");
    2078           0 :                 return NULL;
    2079             :         }
    2080           0 :         tok2 = isl_stream_next_token_on_same_line(s);
    2081           0 :         if (tok2 && tok2->type == ISL_TOKEN_VALUE) {
    2082           0 :                 isl_stream_push_token(s, tok2);
    2083           0 :                 isl_stream_push_token(s, tok);
    2084           0 :                 return isl_map_from_basic_map(basic_map_read_polylib(s));
    2085             :         }
    2086           0 :         if (tok2) {
    2087           0 :                 isl_stream_error(s, tok2, "unexpected token");
    2088           0 :                 isl_stream_push_token(s, tok2);
    2089           0 :                 isl_stream_push_token(s, tok);
    2090           0 :                 return NULL;
    2091             :         }
    2092           0 :         n = isl_int_get_si(tok->u.v);
    2093           0 :         isl_token_free(tok);
    2094             : 
    2095           0 :         isl_assert(s->ctx, n >= 1, return NULL);
    2096             : 
    2097           0 :         map = isl_map_from_basic_map(basic_map_read_polylib(s));
    2098             : 
    2099           0 :         for (i = 1; map && i < n; ++i)
    2100           0 :                 map = isl_map_union(map,
    2101             :                         isl_map_from_basic_map(basic_map_read_polylib(s)));
    2102             : 
    2103           0 :         return map;
    2104             : }
    2105             : 
    2106           0 : static int optional_power(__isl_keep isl_stream *s)
    2107             : {
    2108             :         int pow;
    2109             :         struct isl_token *tok;
    2110             : 
    2111           0 :         tok = isl_stream_next_token(s);
    2112           0 :         if (!tok)
    2113           0 :                 return 1;
    2114           0 :         if (tok->type != '^') {
    2115           0 :                 isl_stream_push_token(s, tok);
    2116           0 :                 return 1;
    2117             :         }
    2118           0 :         isl_token_free(tok);
    2119           0 :         tok = isl_stream_next_token(s);
    2120           0 :         if (!tok || tok->type != ISL_TOKEN_VALUE) {
    2121           0 :                 isl_stream_error(s, tok, "expecting exponent");
    2122           0 :                 if (tok)
    2123           0 :                         isl_stream_push_token(s, tok);
    2124           0 :                 return 1;
    2125             :         }
    2126           0 :         pow = isl_int_get_si(tok->u.v);
    2127           0 :         isl_token_free(tok);
    2128           0 :         return pow;
    2129             : }
    2130             : 
    2131             : static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
    2132             :         __isl_keep isl_map *map, struct vars *v);
    2133             : 
    2134           0 : static __isl_give isl_pw_qpolynomial *read_factor(__isl_keep isl_stream *s,
    2135             :         __isl_keep isl_map *map, struct vars *v)
    2136             : {
    2137             :         isl_pw_qpolynomial *pwqp;
    2138             :         struct isl_token *tok;
    2139             : 
    2140           0 :         tok = next_token(s);
    2141           0 :         if (!tok) {
    2142           0 :                 isl_stream_error(s, NULL, "unexpected EOF");
    2143           0 :                 return NULL;
    2144             :         }
    2145           0 :         if (tok->type == '(') {
    2146             :                 int pow;
    2147             : 
    2148           0 :                 isl_token_free(tok);
    2149           0 :                 pwqp = read_term(s, map, v);
    2150           0 :                 if (!pwqp)
    2151           0 :                         return NULL;
    2152           0 :                 if (isl_stream_eat(s, ')'))
    2153           0 :                         goto error;
    2154           0 :                 pow = optional_power(s);
    2155           0 :                 pwqp = isl_pw_qpolynomial_pow(pwqp, pow);
    2156           0 :         } else if (tok->type == ISL_TOKEN_VALUE) {
    2157             :                 struct isl_token *tok2;
    2158             :                 isl_qpolynomial *qp;
    2159             : 
    2160           0 :                 tok2 = isl_stream_next_token(s);
    2161           0 :                 if (tok2 && tok2->type == '/') {
    2162           0 :                         isl_token_free(tok2);
    2163           0 :                         tok2 = next_token(s);
    2164           0 :                         if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
    2165           0 :                                 isl_stream_error(s, tok2, "expected denominator");
    2166           0 :                                 isl_token_free(tok);
    2167           0 :                                 isl_token_free(tok2);
    2168           0 :                                 return NULL;
    2169             :                         }
    2170           0 :                         qp = isl_qpolynomial_rat_cst_on_domain(isl_map_get_space(map),
    2171           0 :                                                     tok->u.v, tok2->u.v);
    2172           0 :                         isl_token_free(tok2);
    2173             :                 } else {
    2174           0 :                         isl_stream_push_token(s, tok2);
    2175           0 :                         qp = isl_qpolynomial_cst_on_domain(isl_map_get_space(map),
    2176           0 :                                                 tok->u.v);
    2177             :                 }
    2178           0 :                 isl_token_free(tok);
    2179           0 :                 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
    2180           0 :         } else if (tok->type == ISL_TOKEN_INFTY) {
    2181             :                 isl_qpolynomial *qp;
    2182           0 :                 isl_token_free(tok);
    2183           0 :                 qp = isl_qpolynomial_infty_on_domain(isl_map_get_space(map));
    2184           0 :                 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
    2185           0 :         } else if (tok->type == ISL_TOKEN_NAN) {
    2186             :                 isl_qpolynomial *qp;
    2187           0 :                 isl_token_free(tok);
    2188           0 :                 qp = isl_qpolynomial_nan_on_domain(isl_map_get_space(map));
    2189           0 :                 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
    2190           0 :         } else if (tok->type == ISL_TOKEN_IDENT) {
    2191           0 :                 int n = v->n;
    2192           0 :                 int pos = vars_pos(v, tok->u.s, -1);
    2193             :                 int pow;
    2194             :                 isl_qpolynomial *qp;
    2195           0 :                 if (pos < 0) {
    2196           0 :                         isl_token_free(tok);
    2197           0 :                         return NULL;
    2198             :                 }
    2199           0 :                 if (pos >= n) {
    2200           0 :                         vars_drop(v, v->n - n);
    2201           0 :                         isl_stream_error(s, tok, "unknown identifier");
    2202           0 :                         isl_token_free(tok);
    2203           0 :                         return NULL;
    2204             :                 }
    2205           0 :                 isl_token_free(tok);
    2206           0 :                 pow = optional_power(s);
    2207           0 :                 qp = isl_qpolynomial_var_pow_on_domain(isl_map_get_space(map), pos, pow);
    2208           0 :                 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
    2209           0 :         } else if (is_start_of_div(tok)) {
    2210             :                 isl_pw_aff *pwaff;
    2211             :                 int pow;
    2212             : 
    2213           0 :                 isl_stream_push_token(s, tok);
    2214           0 :                 pwaff = accept_div(s, isl_map_get_space(map), v);
    2215           0 :                 pow = optional_power(s);
    2216           0 :                 pwqp = isl_pw_qpolynomial_from_pw_aff(pwaff);
    2217           0 :                 pwqp = isl_pw_qpolynomial_pow(pwqp, pow);
    2218           0 :         } else if (tok->type == '-') {
    2219           0 :                 isl_token_free(tok);
    2220           0 :                 pwqp = read_factor(s, map, v);
    2221           0 :                 pwqp = isl_pw_qpolynomial_neg(pwqp);
    2222             :         } else {
    2223           0 :                 isl_stream_error(s, tok, "unexpected isl_token");
    2224           0 :                 isl_stream_push_token(s, tok);
    2225           0 :                 return NULL;
    2226             :         }
    2227             : 
    2228           0 :         if (isl_stream_eat_if_available(s, '*') ||
    2229           0 :             isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
    2230             :                 isl_pw_qpolynomial *pwqp2;
    2231             : 
    2232           0 :                 pwqp2 = read_factor(s, map, v);
    2233           0 :                 pwqp = isl_pw_qpolynomial_mul(pwqp, pwqp2);
    2234             :         }
    2235             : 
    2236           0 :         return pwqp;
    2237             : error:
    2238           0 :         isl_pw_qpolynomial_free(pwqp);
    2239           0 :         return NULL;
    2240             : }
    2241             : 
    2242           0 : static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
    2243             :         __isl_keep isl_map *map, struct vars *v)
    2244             : {
    2245             :         struct isl_token *tok;
    2246             :         isl_pw_qpolynomial *pwqp;
    2247             : 
    2248           0 :         pwqp = read_factor(s, map, v);
    2249             : 
    2250             :         for (;;) {
    2251           0 :                 tok = next_token(s);
    2252           0 :                 if (!tok)
    2253           0 :                         return pwqp;
    2254             : 
    2255           0 :                 if (tok->type == '+') {
    2256             :                         isl_pw_qpolynomial *pwqp2;
    2257             : 
    2258           0 :                         isl_token_free(tok);
    2259           0 :                         pwqp2 = read_factor(s, map, v);
    2260           0 :                         pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2);
    2261           0 :                 } else if (tok->type == '-') {
    2262             :                         isl_pw_qpolynomial *pwqp2;
    2263             : 
    2264           0 :                         isl_token_free(tok);
    2265           0 :                         pwqp2 = read_factor(s, map, v);
    2266           0 :                         pwqp = isl_pw_qpolynomial_sub(pwqp, pwqp2);
    2267           0 :                 } else if (tok->type == ISL_TOKEN_VALUE &&
    2268           0 :                             isl_int_is_neg(tok->u.v)) {
    2269             :                         isl_pw_qpolynomial *pwqp2;
    2270             : 
    2271           0 :                         isl_stream_push_token(s, tok);
    2272           0 :                         pwqp2 = read_factor(s, map, v);
    2273           0 :                         pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2);
    2274             :                 } else {
    2275           0 :                         isl_stream_push_token(s, tok);
    2276           0 :                         break;
    2277             :                 }
    2278           0 :         }
    2279             : 
    2280           0 :         return pwqp;
    2281             : }
    2282             : 
    2283           0 : static __isl_give isl_map *read_optional_formula(__isl_keep isl_stream *s,
    2284             :         __isl_take isl_map *map, struct vars *v, int rational)
    2285             : {
    2286             :         struct isl_token *tok;
    2287             : 
    2288           0 :         tok = isl_stream_next_token(s);
    2289           0 :         if (!tok) {
    2290           0 :                 isl_stream_error(s, NULL, "unexpected EOF");
    2291           0 :                 goto error;
    2292             :         }
    2293           0 :         if (tok->type == ':' ||
    2294           0 :             (tok->type == ISL_TOKEN_OR && !strcmp(tok->u.s, "|"))) {
    2295           0 :                 isl_token_free(tok);
    2296           0 :                 map = read_formula(s, v, map, rational);
    2297             :         } else
    2298           0 :                 isl_stream_push_token(s, tok);
    2299             : 
    2300           0 :         return map;
    2301             : error:
    2302           0 :         isl_map_free(map);
    2303           0 :         return NULL;
    2304             : }
    2305             : 
    2306           0 : static struct isl_obj obj_read_poly(__isl_keep isl_stream *s,
    2307             :         __isl_take isl_map *map, struct vars *v, int n)
    2308             : {
    2309           0 :         struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL };
    2310             :         isl_pw_qpolynomial *pwqp;
    2311             :         struct isl_set *set;
    2312             : 
    2313           0 :         pwqp = read_term(s, map, v);
    2314           0 :         map = read_optional_formula(s, map, v, 0);
    2315           0 :         set = isl_map_range(map);
    2316             : 
    2317           0 :         pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);
    2318             : 
    2319           0 :         vars_drop(v, v->n - n);
    2320             : 
    2321           0 :         obj.v = pwqp;
    2322           0 :         return obj;
    2323             : }
    2324             : 
    2325           0 : static struct isl_obj obj_read_poly_or_fold(__isl_keep isl_stream *s,
    2326             :         __isl_take isl_set *set, struct vars *v, int n)
    2327             : {
    2328           0 :         struct isl_obj obj = { isl_obj_pw_qpolynomial_fold, NULL };
    2329             :         isl_pw_qpolynomial *pwqp;
    2330           0 :         isl_pw_qpolynomial_fold *pwf = NULL;
    2331             : 
    2332           0 :         if (!isl_stream_eat_if_available(s, ISL_TOKEN_MAX))
    2333           0 :                 return obj_read_poly(s, set, v, n);
    2334             : 
    2335           0 :         if (isl_stream_eat(s, '('))
    2336           0 :                 goto error;
    2337             : 
    2338           0 :         pwqp = read_term(s, set, v);
    2339           0 :         pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max, pwqp);
    2340             : 
    2341           0 :         while (isl_stream_eat_if_available(s, ',')) {
    2342             :                 isl_pw_qpolynomial_fold *pwf_i;
    2343           0 :                 pwqp = read_term(s, set, v);
    2344           0 :                 pwf_i = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max,
    2345             :                                                                         pwqp);
    2346           0 :                 pwf = isl_pw_qpolynomial_fold_fold(pwf, pwf_i);
    2347             :         }
    2348             : 
    2349           0 :         if (isl_stream_eat(s, ')'))
    2350           0 :                 goto error;
    2351             : 
    2352           0 :         set = read_optional_formula(s, set, v, 0);
    2353           0 :         pwf = isl_pw_qpolynomial_fold_intersect_domain(pwf, set);
    2354             : 
    2355           0 :         vars_drop(v, v->n - n);
    2356             : 
    2357           0 :         obj.v = pwf;
    2358           0 :         return obj;
    2359             : error:
    2360           0 :         isl_set_free(set);
    2361           0 :         isl_pw_qpolynomial_fold_free(pwf);
    2362           0 :         obj.type = isl_obj_none;
    2363           0 :         return obj;
    2364             : }
    2365             : 
    2366           0 : static int is_rational(__isl_keep isl_stream *s)
    2367             : {
    2368             :         struct isl_token *tok;
    2369             : 
    2370           0 :         tok = isl_stream_next_token(s);
    2371           0 :         if (!tok)
    2372           0 :                 return 0;
    2373           0 :         if (tok->type == ISL_TOKEN_RAT && isl_stream_next_token_is(s, ':')) {
    2374           0 :                 isl_token_free(tok);
    2375           0 :                 isl_stream_eat(s, ':');
    2376           0 :                 return 1;
    2377             :         }
    2378             : 
    2379           0 :         isl_stream_push_token(s, tok);
    2380             : 
    2381           0 :         return 0;
    2382             : }
    2383             : 
    2384           0 : static struct isl_obj obj_read_body(__isl_keep isl_stream *s,
    2385             :         __isl_take isl_map *map, struct vars *v)
    2386             : {
    2387             :         struct isl_token *tok;
    2388           0 :         struct isl_obj obj = { isl_obj_set, NULL };
    2389           0 :         int n = v->n;
    2390             :         int rational;
    2391             : 
    2392           0 :         rational = is_rational(s);
    2393           0 :         if (rational)
    2394           0 :                 map = isl_map_set_rational(map);
    2395             : 
    2396           0 :         if (isl_stream_next_token_is(s, ':')) {
    2397           0 :                 obj.type = isl_obj_set;
    2398           0 :                 obj.v = read_optional_formula(s, map, v, rational);
    2399           0 :                 return obj;
    2400             :         }
    2401             : 
    2402           0 :         if (!next_is_tuple(s))
    2403           0 :                 return obj_read_poly_or_fold(s, map, v, n);
    2404             : 
    2405           0 :         map = read_map_tuple(s, map, isl_dim_in, v, rational, 0);
    2406           0 :         if (!map)
    2407           0 :                 goto error;
    2408           0 :         tok = isl_stream_next_token(s);
    2409           0 :         if (!tok)
    2410           0 :                 goto error;
    2411           0 :         if (tok->type == ISL_TOKEN_TO) {
    2412           0 :                 obj.type = isl_obj_map;
    2413           0 :                 isl_token_free(tok);
    2414           0 :                 if (!next_is_tuple(s)) {
    2415           0 :                         isl_set *set = isl_map_domain(map);
    2416           0 :                         return obj_read_poly_or_fold(s, set, v, n);
    2417             :                 }
    2418           0 :                 map = read_map_tuple(s, map, isl_dim_out, v, rational, 0);
    2419           0 :                 if (!map)
    2420           0 :                         goto error;
    2421             :         } else {
    2422           0 :                 map = isl_map_domain(map);
    2423           0 :                 isl_stream_push_token(s, tok);
    2424             :         }
    2425             : 
    2426           0 :         map = read_optional_formula(s, map, v, rational);
    2427             : 
    2428           0 :         vars_drop(v, v->n - n);
    2429             : 
    2430           0 :         obj.v = map;
    2431           0 :         return obj;
    2432             : error:
    2433           0 :         isl_map_free(map);
    2434           0 :         obj.type = isl_obj_none;
    2435           0 :         return obj;
    2436             : }
    2437             : 
    2438           0 : static struct isl_obj to_union(isl_ctx *ctx, struct isl_obj obj)
    2439             : {
    2440           0 :         if (obj.type == isl_obj_map) {
    2441           0 :                 obj.v = isl_union_map_from_map(obj.v);
    2442           0 :                 obj.type = isl_obj_union_map;
    2443           0 :         } else if (obj.type == isl_obj_set) {
    2444           0 :                 obj.v = isl_union_set_from_set(obj.v);
    2445           0 :                 obj.type = isl_obj_union_set;
    2446           0 :         } else if (obj.type == isl_obj_pw_qpolynomial) {
    2447           0 :                 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
    2448           0 :                 obj.type = isl_obj_union_pw_qpolynomial;
    2449           0 :         } else if (obj.type == isl_obj_pw_qpolynomial_fold) {
    2450           0 :                 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
    2451           0 :                 obj.type = isl_obj_union_pw_qpolynomial_fold;
    2452             :         } else
    2453           0 :                 isl_assert(ctx, 0, goto error);
    2454           0 :         return obj;
    2455             : error:
    2456           0 :         obj.type->free(obj.v);
    2457           0 :         obj.type = isl_obj_none;
    2458           0 :         return obj;
    2459             : }
    2460             : 
    2461           0 : static struct isl_obj obj_add(__isl_keep isl_stream *s,
    2462             :         struct isl_obj obj1, struct isl_obj obj2)
    2463             : {
    2464           0 :         if (obj2.type == isl_obj_none || !obj2.v)
    2465             :                 goto error;
    2466           0 :         if (obj1.type == isl_obj_set && obj2.type == isl_obj_union_set)
    2467           0 :                 obj1 = to_union(s->ctx, obj1);
    2468           0 :         if (obj1.type == isl_obj_union_set && obj2.type == isl_obj_set)
    2469           0 :                 obj2 = to_union(s->ctx, obj2);
    2470           0 :         if (obj1.type == isl_obj_map && obj2.type == isl_obj_union_map)
    2471           0 :                 obj1 = to_union(s->ctx, obj1);
    2472           0 :         if (obj1.type == isl_obj_union_map && obj2.type == isl_obj_map)
    2473           0 :                 obj2 = to_union(s->ctx, obj2);
    2474           0 :         if (obj1.type == isl_obj_pw_qpolynomial &&
    2475           0 :             obj2.type == isl_obj_union_pw_qpolynomial)
    2476           0 :                 obj1 = to_union(s->ctx, obj1);
    2477           0 :         if (obj1.type == isl_obj_union_pw_qpolynomial &&
    2478           0 :             obj2.type == isl_obj_pw_qpolynomial)
    2479           0 :                 obj2 = to_union(s->ctx, obj2);
    2480           0 :         if (obj1.type == isl_obj_pw_qpolynomial_fold &&
    2481           0 :             obj2.type == isl_obj_union_pw_qpolynomial_fold)
    2482           0 :                 obj1 = to_union(s->ctx, obj1);
    2483           0 :         if (obj1.type == isl_obj_union_pw_qpolynomial_fold &&
    2484           0 :             obj2.type == isl_obj_pw_qpolynomial_fold)
    2485           0 :                 obj2 = to_union(s->ctx, obj2);
    2486           0 :         if (obj1.type != obj2.type) {
    2487           0 :                 isl_stream_error(s, NULL,
    2488             :                                 "attempt to combine incompatible objects");
    2489           0 :                 goto error;
    2490             :         }
    2491           0 :         if (!obj1.type->add)
    2492           0 :                 isl_die(s->ctx, isl_error_internal,
    2493             :                         "combination not supported on object type", goto error);
    2494           0 :         if (obj1.type == isl_obj_map && !isl_map_has_equal_space(obj1.v, obj2.v)) {
    2495           0 :                 obj1 = to_union(s->ctx, obj1);
    2496           0 :                 obj2 = to_union(s->ctx, obj2);
    2497             :         }
    2498           0 :         if (obj1.type == isl_obj_set && !isl_set_has_equal_space(obj1.v, obj2.v)) {
    2499           0 :                 obj1 = to_union(s->ctx, obj1);
    2500           0 :                 obj2 = to_union(s->ctx, obj2);
    2501             :         }
    2502           0 :         if (obj1.type == isl_obj_pw_qpolynomial &&
    2503           0 :             !isl_pw_qpolynomial_has_equal_space(obj1.v, obj2.v)) {
    2504           0 :                 obj1 = to_union(s->ctx, obj1);
    2505           0 :                 obj2 = to_union(s->ctx, obj2);
    2506             :         }
    2507           0 :         if (obj1.type == isl_obj_pw_qpolynomial_fold &&
    2508           0 :             !isl_pw_qpolynomial_fold_has_equal_space(obj1.v, obj2.v)) {
    2509           0 :                 obj1 = to_union(s->ctx, obj1);
    2510           0 :                 obj2 = to_union(s->ctx, obj2);
    2511             :         }
    2512           0 :         obj1.v = obj1.type->add(obj1.v, obj2.v);
    2513           0 :         return obj1;
    2514             : error:
    2515           0 :         obj1.type->free(obj1.v);
    2516           0 :         obj2.type->free(obj2.v);
    2517           0 :         obj1.type = isl_obj_none;
    2518           0 :         obj1.v = NULL;
    2519           0 :         return obj1;
    2520             : }
    2521             : 
    2522             : /* Are the first two tokens on "s", "domain" (either as a string
    2523             :  * or as an identifier) followed by ":"?
    2524             :  */
    2525           0 : static int next_is_domain_colon(__isl_keep isl_stream *s)
    2526             : {
    2527             :         struct isl_token *tok;
    2528             :         char *name;
    2529             :         int res;
    2530             : 
    2531           0 :         tok = isl_stream_next_token(s);
    2532           0 :         if (!tok)
    2533           0 :                 return 0;
    2534           0 :         if (tok->type != ISL_TOKEN_IDENT && tok->type != ISL_TOKEN_STRING) {
    2535           0 :                 isl_stream_push_token(s, tok);
    2536           0 :                 return 0;
    2537             :         }
    2538             : 
    2539           0 :         name = isl_token_get_str(s->ctx, tok);
    2540           0 :         res = !strcmp(name, "domain") && isl_stream_next_token_is(s, ':');
    2541           0 :         free(name);
    2542             : 
    2543           0 :         isl_stream_push_token(s, tok);
    2544             : 
    2545           0 :         return res;
    2546             : }
    2547             : 
    2548             : /* Do the first tokens on "s" look like a schedule?
    2549             :  *
    2550             :  * The root of a schedule is always a domain node, so the first thing
    2551             :  * we expect in the stream is a domain key, i.e., "domain" followed
    2552             :  * by ":".  If the schedule was printed in YAML flow style, then
    2553             :  * we additionally expect a "{" to open the outer mapping.
    2554             :  */
    2555           0 : static int next_is_schedule(__isl_keep isl_stream *s)
    2556             : {
    2557             :         struct isl_token *tok;
    2558             :         int is_schedule;
    2559             : 
    2560           0 :         tok = isl_stream_next_token(s);
    2561           0 :         if (!tok)
    2562           0 :                 return 0;
    2563           0 :         if (tok->type != '{') {
    2564           0 :                 isl_stream_push_token(s, tok);
    2565           0 :                 return next_is_domain_colon(s);
    2566             :         }
    2567             : 
    2568           0 :         is_schedule = next_is_domain_colon(s);
    2569           0 :         isl_stream_push_token(s, tok);
    2570             : 
    2571           0 :         return is_schedule;
    2572             : }
    2573             : 
    2574             : /* Read an isl_schedule from "s" and store it in an isl_obj.
    2575             :  */
    2576           0 : static struct isl_obj schedule_read(__isl_keep isl_stream *s)
    2577             : {
    2578             :         struct isl_obj obj;
    2579             : 
    2580           0 :         obj.type = isl_obj_schedule;
    2581           0 :         obj.v = isl_stream_read_schedule(s);
    2582             : 
    2583           0 :         return obj;
    2584             : }
    2585             : 
    2586             : /* Read a disjunction of object bodies from "s".
    2587             :  * That is, read the inside of the braces, but not the braces themselves.
    2588             :  * "v" contains a description of the identifiers parsed so far.
    2589             :  * "map" contains information about the parameters.
    2590             :  */
    2591           0 : static struct isl_obj obj_read_disjuncts(__isl_keep isl_stream *s,
    2592             :         struct vars *v, __isl_keep isl_map *map)
    2593             : {
    2594           0 :         struct isl_obj obj = { isl_obj_set, NULL };
    2595             : 
    2596           0 :         if (isl_stream_next_token_is(s, '}')) {
    2597           0 :                 obj.type = isl_obj_union_set;
    2598           0 :                 obj.v = isl_union_set_empty(isl_map_get_space(map));
    2599           0 :                 return obj;
    2600             :         }
    2601             : 
    2602             :         for (;;) {
    2603             :                 struct isl_obj o;
    2604           0 :                 o = obj_read_body(s, isl_map_copy(map), v);
    2605           0 :                 if (!obj.v)
    2606           0 :                         obj = o;
    2607             :                 else
    2608           0 :                         obj = obj_add(s, obj, o);
    2609           0 :                 if (obj.type == isl_obj_none || !obj.v)
    2610           0 :                         return obj;
    2611           0 :                 if (!isl_stream_eat_if_available(s, ';'))
    2612           0 :                         break;
    2613           0 :                 if (isl_stream_next_token_is(s, '}'))
    2614           0 :                         break;
    2615           0 :         }
    2616             : 
    2617           0 :         return obj;
    2618             : }
    2619             : 
    2620           0 : static struct isl_obj obj_read(__isl_keep isl_stream *s)
    2621             : {
    2622           0 :         isl_map *map = NULL;
    2623             :         struct isl_token *tok;
    2624           0 :         struct vars *v = NULL;
    2625           0 :         struct isl_obj obj = { isl_obj_set, NULL };
    2626             : 
    2627           0 :         if (next_is_schedule(s))
    2628           0 :                 return schedule_read(s);
    2629             : 
    2630           0 :         tok = next_token(s);
    2631           0 :         if (!tok) {
    2632           0 :                 isl_stream_error(s, NULL, "unexpected EOF");
    2633           0 :                 goto error;
    2634             :         }
    2635           0 :         if (tok->type == ISL_TOKEN_VALUE) {
    2636             :                 struct isl_token *tok2;
    2637             :                 struct isl_map *map;
    2638             : 
    2639           0 :                 tok2 = isl_stream_next_token(s);
    2640           0 :                 if (!tok2 || tok2->type != ISL_TOKEN_VALUE ||
    2641           0 :                     isl_int_is_neg(tok2->u.v)) {
    2642           0 :                         if (tok2)
    2643           0 :                                 isl_stream_push_token(s, tok2);
    2644           0 :                         obj.type = isl_obj_val;
    2645           0 :                         obj.v = isl_val_int_from_isl_int(s->ctx, tok->u.v);
    2646           0 :                         isl_token_free(tok);
    2647           0 :                         return obj;
    2648             :                 }
    2649           0 :                 isl_stream_push_token(s, tok2);
    2650           0 :                 isl_stream_push_token(s, tok);
    2651           0 :                 map = map_read_polylib(s);
    2652           0 :                 if (!map)
    2653           0 :                         goto error;
    2654           0 :                 if (isl_map_may_be_set(map))
    2655           0 :                         obj.v = isl_map_range(map);
    2656             :                 else {
    2657           0 :                         obj.type = isl_obj_map;
    2658           0 :                         obj.v = map;
    2659             :                 }
    2660           0 :                 return obj;
    2661             :         }
    2662           0 :         v = vars_new(s->ctx);
    2663           0 :         if (!v) {
    2664           0 :                 isl_stream_push_token(s, tok);
    2665           0 :                 goto error;
    2666             :         }
    2667           0 :         map = isl_map_universe(isl_space_params_alloc(s->ctx, 0));
    2668           0 :         if (tok->type == '[') {
    2669           0 :                 isl_stream_push_token(s, tok);
    2670           0 :                 map = read_map_tuple(s, map, isl_dim_param, v, 0, 0);
    2671           0 :                 if (!map)
    2672           0 :                         goto error;
    2673           0 :                 tok = isl_stream_next_token(s);
    2674           0 :                 if (!tok || tok->type != ISL_TOKEN_TO) {
    2675           0 :                         isl_stream_error(s, tok, "expecting '->'");
    2676           0 :                         if (tok)
    2677           0 :                                 isl_stream_push_token(s, tok);
    2678           0 :                         goto error;
    2679             :                 }
    2680           0 :                 isl_token_free(tok);
    2681           0 :                 tok = isl_stream_next_token(s);
    2682             :         }
    2683           0 :         if (!tok || tok->type != '{') {
    2684           0 :                 isl_stream_error(s, tok, "expecting '{'");
    2685           0 :                 if (tok)
    2686           0 :                         isl_stream_push_token(s, tok);
    2687           0 :                 goto error;
    2688             :         }
    2689           0 :         isl_token_free(tok);
    2690             : 
    2691           0 :         tok = isl_stream_next_token(s);
    2692           0 :         if (!tok)
    2693             :                 ;
    2694           0 :         else if (tok->type == ISL_TOKEN_IDENT && !strcmp(tok->u.s, "Sym")) {
    2695           0 :                 isl_token_free(tok);
    2696           0 :                 if (isl_stream_eat(s, '='))
    2697           0 :                         goto error;
    2698           0 :                 map = read_map_tuple(s, map, isl_dim_param, v, 0, 1);
    2699           0 :                 if (!map)
    2700           0 :                         goto error;
    2701             :         } else
    2702           0 :                 isl_stream_push_token(s, tok);
    2703             : 
    2704           0 :         obj = obj_read_disjuncts(s, v, map);
    2705           0 :         if (obj.type == isl_obj_none || !obj.v)
    2706             :                 goto error;
    2707             : 
    2708           0 :         tok = isl_stream_next_token(s);
    2709           0 :         if (tok && tok->type == '}') {
    2710           0 :                 isl_token_free(tok);
    2711             :         } else {
    2712           0 :                 isl_stream_error(s, tok, "unexpected isl_token");
    2713           0 :                 if (tok)
    2714           0 :                         isl_token_free(tok);
    2715           0 :                 goto error;
    2716             :         }
    2717             : 
    2718           0 :         vars_free(v);
    2719           0 :         isl_map_free(map);
    2720             : 
    2721           0 :         return obj;
    2722             : error:
    2723           0 :         isl_map_free(map);
    2724           0 :         obj.type->free(obj.v);
    2725           0 :         if (v)
    2726           0 :                 vars_free(v);
    2727           0 :         obj.v = NULL;
    2728           0 :         return obj;
    2729             : }
    2730             : 
    2731           0 : struct isl_obj isl_stream_read_obj(__isl_keep isl_stream *s)
    2732             : {
    2733           0 :         return obj_read(s);
    2734             : }
    2735             : 
    2736           0 : __isl_give isl_map *isl_stream_read_map(__isl_keep isl_stream *s)
    2737             : {
    2738             :         struct isl_obj obj;
    2739             : 
    2740           0 :         obj = obj_read(s);
    2741           0 :         if (obj.v)
    2742           0 :                 isl_assert(s->ctx, obj.type == isl_obj_map ||
    2743             :                                    obj.type == isl_obj_set, goto error);
    2744             :         
    2745           0 :         if (obj.type == isl_obj_set)
    2746           0 :                 obj.v = isl_map_from_range(obj.v);
    2747             : 
    2748           0 :         return obj.v;
    2749             : error:
    2750           0 :         obj.type->free(obj.v);
    2751           0 :         return NULL;
    2752             : }
    2753             : 
    2754           0 : __isl_give isl_set *isl_stream_read_set(__isl_keep isl_stream *s)
    2755             : {
    2756             :         struct isl_obj obj;
    2757             : 
    2758           0 :         obj = obj_read(s);
    2759           0 :         if (obj.v) {
    2760           0 :                 if (obj.type == isl_obj_map && isl_map_may_be_set(obj.v)) {
    2761           0 :                         obj.v = isl_map_range(obj.v);
    2762           0 :                         obj.type = isl_obj_set;
    2763             :                 }
    2764           0 :                 isl_assert(s->ctx, obj.type == isl_obj_set, goto error);
    2765             :         }
    2766             : 
    2767           0 :         return obj.v;
    2768             : error:
    2769           0 :         obj.type->free(obj.v);
    2770           0 :         return NULL;
    2771             : }
    2772             : 
    2773           0 : __isl_give isl_union_map *isl_stream_read_union_map(__isl_keep isl_stream *s)
    2774             : {
    2775             :         struct isl_obj obj;
    2776             : 
    2777           0 :         obj = obj_read(s);
    2778           0 :         if (obj.type == isl_obj_map) {
    2779           0 :                 obj.type = isl_obj_union_map;
    2780           0 :                 obj.v = isl_union_map_from_map(obj.v);
    2781             :         }
    2782           0 :         if (obj.type == isl_obj_set) {
    2783           0 :                 obj.type = isl_obj_union_set;
    2784           0 :                 obj.v = isl_union_set_from_set(obj.v);
    2785             :         }
    2786           0 :         if (obj.v && obj.type == isl_obj_union_set &&
    2787           0 :             isl_union_set_is_empty(obj.v))
    2788           0 :                 obj.type = isl_obj_union_map;
    2789           0 :         if (obj.v && obj.type != isl_obj_union_map)
    2790           0 :                 isl_die(s->ctx, isl_error_invalid, "invalid input", goto error);
    2791             : 
    2792           0 :         return obj.v;
    2793             : error:
    2794           0 :         obj.type->free(obj.v);
    2795           0 :         return NULL;
    2796             : }
    2797             : 
    2798             : /* Extract an isl_union_set from "obj".
    2799             :  * This only works if the object was detected as either a set
    2800             :  * (in which case it is converted to a union set) or a union set.
    2801             :  */
    2802           0 : static __isl_give isl_union_set *extract_union_set(isl_ctx *ctx,
    2803             :         struct isl_obj obj)
    2804             : {
    2805           0 :         if (obj.type == isl_obj_set) {
    2806           0 :                 obj.type = isl_obj_union_set;
    2807           0 :                 obj.v = isl_union_set_from_set(obj.v);
    2808             :         }
    2809           0 :         if (obj.v)
    2810           0 :                 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
    2811             : 
    2812           0 :         return obj.v;
    2813             : error:
    2814           0 :         obj.type->free(obj.v);
    2815           0 :         return NULL;
    2816             : }
    2817             : 
    2818             : /* Read an isl_union_set from "s".
    2819             :  * First read a generic object and then try and extract
    2820             :  * an isl_union_set from that.
    2821             :  */
    2822           0 : __isl_give isl_union_set *isl_stream_read_union_set(__isl_keep isl_stream *s)
    2823             : {
    2824             :         struct isl_obj obj;
    2825             : 
    2826           0 :         obj = obj_read(s);
    2827           0 :         return extract_union_set(s->ctx, obj);
    2828             : }
    2829             : 
    2830           0 : static __isl_give isl_basic_map *basic_map_read(__isl_keep isl_stream *s)
    2831             : {
    2832             :         struct isl_obj obj;
    2833             :         struct isl_map *map;
    2834             :         struct isl_basic_map *bmap;
    2835             : 
    2836           0 :         obj = obj_read(s);
    2837           0 :         if (obj.v && (obj.type != isl_obj_map && obj.type != isl_obj_set))
    2838           0 :                 isl_die(s->ctx, isl_error_invalid, "not a (basic) set or map",
    2839             :                         goto error);
    2840           0 :         map = obj.v;
    2841           0 :         if (!map)
    2842           0 :                 return NULL;
    2843             : 
    2844           0 :         if (map->n > 1)
    2845           0 :                 isl_die(s->ctx, isl_error_invalid,
    2846             :                         "set or map description involves "
    2847             :                         "more than one disjunct", goto error);
    2848             : 
    2849           0 :         if (map->n == 0)
    2850           0 :                 bmap = isl_basic_map_empty(isl_map_get_space(map));
    2851             :         else
    2852           0 :                 bmap = isl_basic_map_copy(map->p[0]);
    2853             : 
    2854           0 :         isl_map_free(map);
    2855             : 
    2856           0 :         return bmap;
    2857             : error:
    2858           0 :         obj.type->free(obj.v);
    2859           0 :         return NULL;
    2860             : }
    2861             : 
    2862           0 : static __isl_give isl_basic_set *basic_set_read(__isl_keep isl_stream *s)
    2863             : {
    2864             :         isl_basic_map *bmap;
    2865           0 :         bmap = basic_map_read(s);
    2866           0 :         if (!bmap)
    2867           0 :                 return NULL;
    2868           0 :         if (!isl_basic_map_may_be_set(bmap))
    2869           0 :                 isl_die(s->ctx, isl_error_invalid,
    2870             :                         "input is not a set", goto error);
    2871           0 :         return isl_basic_map_range(bmap);
    2872             : error:
    2873           0 :         isl_basic_map_free(bmap);
    2874           0 :         return NULL;
    2875             : }
    2876             : 
    2877           0 : __isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
    2878             :         FILE *input)
    2879             : {
    2880             :         struct isl_basic_map *bmap;
    2881           0 :         isl_stream *s = isl_stream_new_file(ctx, input);
    2882           0 :         if (!s)
    2883           0 :                 return NULL;
    2884           0 :         bmap = basic_map_read(s);
    2885           0 :         isl_stream_free(s);
    2886           0 :         return bmap;
    2887             : }
    2888             : 
    2889           0 : __isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
    2890             :         FILE *input)
    2891             : {
    2892             :         isl_basic_set *bset;
    2893           0 :         isl_stream *s = isl_stream_new_file(ctx, input);
    2894           0 :         if (!s)
    2895           0 :                 return NULL;
    2896           0 :         bset = basic_set_read(s);
    2897           0 :         isl_stream_free(s);
    2898           0 :         return bset;
    2899             : }
    2900             : 
    2901           0 : struct isl_basic_map *isl_basic_map_read_from_str(struct isl_ctx *ctx,
    2902             :         const char *str)
    2903             : {
    2904             :         struct isl_basic_map *bmap;
    2905           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    2906           0 :         if (!s)
    2907           0 :                 return NULL;
    2908           0 :         bmap = basic_map_read(s);
    2909           0 :         isl_stream_free(s);
    2910           0 :         return bmap;
    2911             : }
    2912             : 
    2913           0 : struct isl_basic_set *isl_basic_set_read_from_str(struct isl_ctx *ctx,
    2914             :         const char *str)
    2915             : {
    2916             :         isl_basic_set *bset;
    2917           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    2918           0 :         if (!s)
    2919           0 :                 return NULL;
    2920           0 :         bset = basic_set_read(s);
    2921           0 :         isl_stream_free(s);
    2922           0 :         return bset;
    2923             : }
    2924             : 
    2925           0 : __isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx,
    2926             :         FILE *input)
    2927             : {
    2928             :         struct isl_map *map;
    2929           0 :         isl_stream *s = isl_stream_new_file(ctx, input);
    2930           0 :         if (!s)
    2931           0 :                 return NULL;
    2932           0 :         map = isl_stream_read_map(s);
    2933           0 :         isl_stream_free(s);
    2934           0 :         return map;
    2935             : }
    2936             : 
    2937           0 : __isl_give isl_map *isl_map_read_from_str(struct isl_ctx *ctx,
    2938             :         const char *str)
    2939             : {
    2940             :         struct isl_map *map;
    2941           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    2942           0 :         if (!s)
    2943           0 :                 return NULL;
    2944           0 :         map = isl_stream_read_map(s);
    2945           0 :         isl_stream_free(s);
    2946           0 :         return map;
    2947             : }
    2948             : 
    2949           0 : __isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx,
    2950             :         FILE *input)
    2951             : {
    2952             :         isl_set *set;
    2953           0 :         isl_stream *s = isl_stream_new_file(ctx, input);
    2954           0 :         if (!s)
    2955           0 :                 return NULL;
    2956           0 :         set = isl_stream_read_set(s);
    2957           0 :         isl_stream_free(s);
    2958           0 :         return set;
    2959             : }
    2960             : 
    2961           0 : struct isl_set *isl_set_read_from_str(struct isl_ctx *ctx,
    2962             :         const char *str)
    2963             : {
    2964             :         isl_set *set;
    2965           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    2966           0 :         if (!s)
    2967           0 :                 return NULL;
    2968           0 :         set = isl_stream_read_set(s);
    2969           0 :         isl_stream_free(s);
    2970           0 :         return set;
    2971             : }
    2972             : 
    2973           0 : __isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx,
    2974             :         FILE *input)
    2975             : {
    2976             :         isl_union_map *umap;
    2977           0 :         isl_stream *s = isl_stream_new_file(ctx, input);
    2978           0 :         if (!s)
    2979           0 :                 return NULL;
    2980           0 :         umap = isl_stream_read_union_map(s);
    2981           0 :         isl_stream_free(s);
    2982           0 :         return umap;
    2983             : }
    2984             : 
    2985           0 : __isl_give isl_union_map *isl_union_map_read_from_str(struct isl_ctx *ctx,
    2986             :                 const char *str)
    2987             : {
    2988             :         isl_union_map *umap;
    2989           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    2990           0 :         if (!s)
    2991           0 :                 return NULL;
    2992           0 :         umap = isl_stream_read_union_map(s);
    2993           0 :         isl_stream_free(s);
    2994           0 :         return umap;
    2995             : }
    2996             : 
    2997           0 : __isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx,
    2998             :         FILE *input)
    2999             : {
    3000             :         isl_union_set *uset;
    3001           0 :         isl_stream *s = isl_stream_new_file(ctx, input);
    3002           0 :         if (!s)
    3003           0 :                 return NULL;
    3004           0 :         uset = isl_stream_read_union_set(s);
    3005           0 :         isl_stream_free(s);
    3006           0 :         return uset;
    3007             : }
    3008             : 
    3009           0 : __isl_give isl_union_set *isl_union_set_read_from_str(struct isl_ctx *ctx,
    3010             :                 const char *str)
    3011             : {
    3012             :         isl_union_set *uset;
    3013           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3014           0 :         if (!s)
    3015           0 :                 return NULL;
    3016           0 :         uset = isl_stream_read_union_set(s);
    3017           0 :         isl_stream_free(s);
    3018           0 :         return uset;
    3019             : }
    3020             : 
    3021           0 : static __isl_give isl_vec *isl_vec_read_polylib(__isl_keep isl_stream *s)
    3022             : {
    3023           0 :         struct isl_vec *vec = NULL;
    3024             :         struct isl_token *tok;
    3025             :         unsigned size;
    3026             :         int j;
    3027             : 
    3028           0 :         tok = isl_stream_next_token(s);
    3029           0 :         if (!tok || tok->type != ISL_TOKEN_VALUE) {
    3030           0 :                 isl_stream_error(s, tok, "expecting vector length");
    3031           0 :                 goto error;
    3032             :         }
    3033             : 
    3034           0 :         size = isl_int_get_si(tok->u.v);
    3035           0 :         isl_token_free(tok);
    3036             : 
    3037           0 :         vec = isl_vec_alloc(s->ctx, size);
    3038             : 
    3039           0 :         for (j = 0; j < size; ++j) {
    3040           0 :                 tok = isl_stream_next_token(s);
    3041           0 :                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
    3042           0 :                         isl_stream_error(s, tok, "expecting constant value");
    3043           0 :                         goto error;
    3044             :                 }
    3045           0 :                 isl_int_set(vec->el[j], tok->u.v);
    3046           0 :                 isl_token_free(tok);
    3047             :         }
    3048             : 
    3049           0 :         return vec;
    3050             : error:
    3051           0 :         isl_token_free(tok);
    3052           0 :         isl_vec_free(vec);
    3053           0 :         return NULL;
    3054             : }
    3055             : 
    3056           0 : static __isl_give isl_vec *vec_read(__isl_keep isl_stream *s)
    3057             : {
    3058           0 :         return isl_vec_read_polylib(s);
    3059             : }
    3060             : 
    3061           0 : __isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input)
    3062             : {
    3063             :         isl_vec *v;
    3064           0 :         isl_stream *s = isl_stream_new_file(ctx, input);
    3065           0 :         if (!s)
    3066           0 :                 return NULL;
    3067           0 :         v = vec_read(s);
    3068           0 :         isl_stream_free(s);
    3069           0 :         return v;
    3070             : }
    3071             : 
    3072           0 : __isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
    3073             :         __isl_keep isl_stream *s)
    3074             : {
    3075             :         struct isl_obj obj;
    3076             : 
    3077           0 :         obj = obj_read(s);
    3078           0 :         if (obj.v)
    3079           0 :                 isl_assert(s->ctx, obj.type == isl_obj_pw_qpolynomial,
    3080             :                            goto error);
    3081             : 
    3082           0 :         return obj.v;
    3083             : error:
    3084           0 :         obj.type->free(obj.v);
    3085           0 :         return NULL;
    3086             : }
    3087             : 
    3088           0 : __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx,
    3089             :                 const char *str)
    3090             : {
    3091             :         isl_pw_qpolynomial *pwqp;
    3092           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3093           0 :         if (!s)
    3094           0 :                 return NULL;
    3095           0 :         pwqp = isl_stream_read_pw_qpolynomial(s);
    3096           0 :         isl_stream_free(s);
    3097           0 :         return pwqp;
    3098             : }
    3099             : 
    3100           0 : __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx,
    3101             :                 FILE *input)
    3102             : {
    3103             :         isl_pw_qpolynomial *pwqp;
    3104           0 :         isl_stream *s = isl_stream_new_file(ctx, input);
    3105           0 :         if (!s)
    3106           0 :                 return NULL;
    3107           0 :         pwqp = isl_stream_read_pw_qpolynomial(s);
    3108           0 :         isl_stream_free(s);
    3109           0 :         return pwqp;
    3110             : }
    3111             : 
    3112             : /* Is the next token an identifer not in "v"?
    3113             :  */
    3114           0 : static int next_is_fresh_ident(__isl_keep isl_stream *s, struct vars *v)
    3115             : {
    3116           0 :         int n = v->n;
    3117             :         int fresh;
    3118             :         struct isl_token *tok;
    3119             : 
    3120           0 :         tok = isl_stream_next_token(s);
    3121           0 :         if (!tok)
    3122           0 :                 return 0;
    3123           0 :         fresh = tok->type == ISL_TOKEN_IDENT && vars_pos(v, tok->u.s, -1) >= n;
    3124           0 :         isl_stream_push_token(s, tok);
    3125             : 
    3126           0 :         vars_drop(v, v->n - n);
    3127             : 
    3128           0 :         return fresh;
    3129             : }
    3130             : 
    3131             : /* First read the domain of the affine expression, which may be
    3132             :  * a parameter space or a set.
    3133             :  * The tricky part is that we don't know if the domain is a set or not,
    3134             :  * so when we are trying to read the domain, we may actually be reading
    3135             :  * the affine expression itself (defined on a parameter domains)
    3136             :  * If the tuple we are reading is named, we assume it's the domain.
    3137             :  * Also, if inside the tuple, the first thing we find is a nested tuple
    3138             :  * or a new identifier, we again assume it's the domain.
    3139             :  * Finally, if the tuple is empty, then it must be the domain
    3140             :  * since it does not contain an affine expression.
    3141             :  * Otherwise, we assume we are reading an affine expression.
    3142             :  */
    3143           0 : static __isl_give isl_set *read_aff_domain(__isl_keep isl_stream *s,
    3144             :         __isl_take isl_set *dom, struct vars *v)
    3145             : {
    3146             :         struct isl_token *tok, *tok2;
    3147             :         int is_empty;
    3148             : 
    3149           0 :         tok = isl_stream_next_token(s);
    3150           0 :         if (tok && (tok->type == ISL_TOKEN_IDENT || tok->is_keyword)) {
    3151           0 :                 isl_stream_push_token(s, tok);
    3152           0 :                 return read_map_tuple(s, dom, isl_dim_set, v, 0, 0);
    3153             :         }
    3154           0 :         if (!tok || tok->type != '[') {
    3155           0 :                 isl_stream_error(s, tok, "expecting '['");
    3156           0 :                 goto error;
    3157             :         }
    3158           0 :         tok2 = isl_stream_next_token(s);
    3159           0 :         is_empty = tok2 && tok2->type == ']';
    3160           0 :         if (tok2)
    3161           0 :                 isl_stream_push_token(s, tok2);
    3162           0 :         if (is_empty || next_is_tuple(s) || next_is_fresh_ident(s, v)) {
    3163           0 :                 isl_stream_push_token(s, tok);
    3164           0 :                 dom = read_map_tuple(s, dom, isl_dim_set, v, 0, 0);
    3165             :         } else
    3166           0 :                 isl_stream_push_token(s, tok);
    3167             : 
    3168           0 :         return dom;
    3169             : error:
    3170           0 :         if (tok)
    3171           0 :                 isl_stream_push_token(s, tok);
    3172           0 :         isl_set_free(dom);
    3173           0 :         return NULL;
    3174             : }
    3175             : 
    3176             : /* Read an affine expression from "s".
    3177             :  */
    3178           0 : __isl_give isl_aff *isl_stream_read_aff(__isl_keep isl_stream *s)
    3179             : {
    3180             :         isl_aff *aff;
    3181             :         isl_multi_aff *ma;
    3182             : 
    3183           0 :         ma = isl_stream_read_multi_aff(s);
    3184           0 :         if (!ma)
    3185           0 :                 return NULL;
    3186           0 :         if (isl_multi_aff_dim(ma, isl_dim_out) != 1)
    3187           0 :                 isl_die(s->ctx, isl_error_invalid,
    3188             :                         "expecting single affine expression",
    3189             :                         goto error);
    3190             : 
    3191           0 :         aff = isl_multi_aff_get_aff(ma, 0);
    3192           0 :         isl_multi_aff_free(ma);
    3193           0 :         return aff;
    3194             : error:
    3195           0 :         isl_multi_aff_free(ma);
    3196           0 :         return NULL;
    3197             : }
    3198             : 
    3199             : /* Read a piecewise affine expression from "s" with domain (space) "dom".
    3200             :  */
    3201           0 : static __isl_give isl_pw_aff *read_pw_aff_with_dom(__isl_keep isl_stream *s,
    3202             :         __isl_take isl_set *dom, struct vars *v)
    3203             : {
    3204           0 :         isl_pw_aff *pwaff = NULL;
    3205             : 
    3206           0 :         if (!isl_set_is_params(dom) && isl_stream_eat(s, ISL_TOKEN_TO))
    3207           0 :                 goto error;
    3208             : 
    3209           0 :         if (isl_stream_eat(s, '['))
    3210           0 :                 goto error;
    3211             : 
    3212           0 :         pwaff = accept_affine(s, isl_set_get_space(dom), v);
    3213             : 
    3214           0 :         if (isl_stream_eat(s, ']'))
    3215           0 :                 goto error;
    3216             : 
    3217           0 :         dom = read_optional_formula(s, dom, v, 0);
    3218           0 :         pwaff = isl_pw_aff_intersect_domain(pwaff, dom);
    3219             : 
    3220           0 :         return pwaff;
    3221             : error:
    3222           0 :         isl_set_free(dom);
    3223           0 :         isl_pw_aff_free(pwaff);
    3224           0 :         return NULL;
    3225             : }
    3226             : 
    3227           0 : __isl_give isl_pw_aff *isl_stream_read_pw_aff(__isl_keep isl_stream *s)
    3228             : {
    3229             :         struct vars *v;
    3230           0 :         isl_set *dom = NULL;
    3231             :         isl_set *aff_dom;
    3232           0 :         isl_pw_aff *pa = NULL;
    3233             :         int n;
    3234             : 
    3235           0 :         v = vars_new(s->ctx);
    3236           0 :         if (!v)
    3237           0 :                 return NULL;
    3238             : 
    3239           0 :         dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
    3240           0 :         if (next_is_tuple(s)) {
    3241           0 :                 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
    3242           0 :                 if (isl_stream_eat(s, ISL_TOKEN_TO))
    3243           0 :                         goto error;
    3244             :         }
    3245           0 :         if (isl_stream_eat(s, '{'))
    3246           0 :                 goto error;
    3247             : 
    3248           0 :         n = v->n;
    3249           0 :         aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
    3250           0 :         pa = read_pw_aff_with_dom(s, aff_dom, v);
    3251           0 :         vars_drop(v, v->n - n);
    3252             : 
    3253           0 :         while (isl_stream_eat_if_available(s, ';')) {
    3254             :                 isl_pw_aff *pa_i;
    3255             : 
    3256           0 :                 n = v->n;
    3257           0 :                 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
    3258           0 :                 pa_i = read_pw_aff_with_dom(s, aff_dom, v);
    3259           0 :                 vars_drop(v, v->n - n);
    3260             : 
    3261           0 :                 pa = isl_pw_aff_union_add(pa, pa_i);
    3262             :         }
    3263             : 
    3264           0 :         if (isl_stream_eat(s, '}'))
    3265           0 :                 goto error;
    3266             : 
    3267           0 :         vars_free(v);
    3268           0 :         isl_set_free(dom);
    3269           0 :         return pa;
    3270             : error:
    3271           0 :         vars_free(v);
    3272           0 :         isl_set_free(dom);
    3273           0 :         isl_pw_aff_free(pa);
    3274           0 :         return NULL;
    3275             : }
    3276             : 
    3277           0 : __isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str)
    3278             : {
    3279             :         isl_aff *aff;
    3280           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3281           0 :         if (!s)
    3282           0 :                 return NULL;
    3283           0 :         aff = isl_stream_read_aff(s);
    3284           0 :         isl_stream_free(s);
    3285           0 :         return aff;
    3286             : }
    3287             : 
    3288           0 : __isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str)
    3289             : {
    3290             :         isl_pw_aff *pa;
    3291           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3292           0 :         if (!s)
    3293           0 :                 return NULL;
    3294           0 :         pa = isl_stream_read_pw_aff(s);
    3295           0 :         isl_stream_free(s);
    3296           0 :         return pa;
    3297             : }
    3298             : 
    3299             : /* Extract an isl_multi_pw_aff with domain space "dom_space"
    3300             :  * from a tuple "tuple" read by read_tuple.
    3301             :  *
    3302             :  * Note that the function read_tuple accepts tuples where some output or
    3303             :  * set dimensions are defined in terms of other output or set dimensions
    3304             :  * since this function is also used to read maps.  As a special case,
    3305             :  * read_tuple also accept dimensions that are defined in terms of themselves
    3306             :  * (i.e., that are not defined).
    3307             :  * These cases are not allowed when extracting an isl_multi_pw_aff so check
    3308             :  * that the definitions of the output/set dimensions do not involve any
    3309             :  * output/set dimensions.
    3310             :  * Finally, drop the output dimensions from the domain of the result
    3311             :  * of read_tuple (which is of the form [input, output] -> [output],
    3312             :  * with anonymous domain) and reset the space.
    3313             :  */
    3314           0 : static __isl_give isl_multi_pw_aff *extract_mpa_from_tuple(
    3315             :         __isl_take isl_space *dom_space, __isl_keep isl_multi_pw_aff *tuple)
    3316             : {
    3317             :         int dim, i, n;
    3318             :         isl_space *space;
    3319             :         isl_multi_pw_aff *mpa;
    3320             : 
    3321           0 :         n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
    3322           0 :         dim = isl_space_dim(dom_space, isl_dim_all);
    3323           0 :         space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
    3324           0 :         space = isl_space_align_params(space, isl_space_copy(dom_space));
    3325           0 :         if (!isl_space_is_params(dom_space))
    3326           0 :                 space = isl_space_map_from_domain_and_range(
    3327             :                                 isl_space_copy(dom_space), space);
    3328           0 :         isl_space_free(dom_space);
    3329           0 :         mpa = isl_multi_pw_aff_alloc(space);
    3330             : 
    3331           0 :         for (i = 0; i < n; ++i) {
    3332             :                 isl_pw_aff *pa;
    3333           0 :                 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
    3334           0 :                 if (!pa)
    3335           0 :                         return isl_multi_pw_aff_free(mpa);
    3336           0 :                 if (isl_pw_aff_involves_dims(pa, isl_dim_in, dim, i + 1)) {
    3337           0 :                         isl_ctx *ctx = isl_pw_aff_get_ctx(pa);
    3338           0 :                         isl_pw_aff_free(pa);
    3339           0 :                         isl_die(ctx, isl_error_invalid,
    3340             :                                 "not an affine expression",
    3341             :                                 return isl_multi_pw_aff_free(mpa));
    3342             :                 }
    3343           0 :                 pa = isl_pw_aff_drop_dims(pa, isl_dim_in, dim, n);
    3344           0 :                 space = isl_multi_pw_aff_get_domain_space(mpa);
    3345           0 :                 pa = isl_pw_aff_reset_domain_space(pa, space);
    3346           0 :                 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
    3347             :         }
    3348             : 
    3349           0 :         return mpa;
    3350             : }
    3351             : 
    3352             : /* Read a tuple of affine expressions, together with optional constraints
    3353             :  * on the domain from "s".  "dom" represents the initial constraints
    3354             :  * on the domain.
    3355             :  *
    3356             :  * The isl_multi_aff may live in either a set or a map space.
    3357             :  * First read the first tuple and check if it is followed by a "->".
    3358             :  * If so, convert the tuple into the domain of the isl_multi_pw_aff and
    3359             :  * read in the next tuple.  This tuple (or the first tuple if it was
    3360             :  * not followed by a "->") is then converted into an isl_multi_pw_aff
    3361             :  * through a call to extract_mpa_from_tuple.
    3362             :  * The result is converted to an isl_pw_multi_aff and
    3363             :  * its domain is intersected with the domain.
    3364             :  */
    3365           0 : static __isl_give isl_pw_multi_aff *read_conditional_multi_aff(
    3366             :         __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v)
    3367             : {
    3368             :         isl_multi_pw_aff *tuple;
    3369             :         isl_multi_pw_aff *mpa;
    3370             :         isl_pw_multi_aff *pma;
    3371           0 :         int n = v->n;
    3372             : 
    3373           0 :         tuple = read_tuple(s, v, 0, 0);
    3374           0 :         if (!tuple)
    3375           0 :                 goto error;
    3376           0 :         if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
    3377           0 :                 isl_map *map = map_from_tuple(tuple, dom, isl_dim_in, v, 0);
    3378           0 :                 dom = isl_map_domain(map);
    3379           0 :                 tuple = read_tuple(s, v, 0, 0);
    3380           0 :                 if (!tuple)
    3381           0 :                         goto error;
    3382             :         }
    3383             : 
    3384           0 :         dom = read_optional_formula(s, dom, v, 0);
    3385             : 
    3386           0 :         vars_drop(v, v->n - n);
    3387             : 
    3388           0 :         mpa = extract_mpa_from_tuple(isl_set_get_space(dom), tuple);
    3389           0 :         isl_multi_pw_aff_free(tuple);
    3390           0 :         pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
    3391           0 :         pma = isl_pw_multi_aff_intersect_domain(pma, dom);
    3392             : 
    3393           0 :         return pma;
    3394             : error:
    3395           0 :         isl_set_free(dom);
    3396           0 :         return NULL;
    3397             : }
    3398             : 
    3399             : /* Read an isl_pw_multi_aff from "s".
    3400             :  *
    3401             :  * In particular, first read the parameters and then read a sequence
    3402             :  * of one or more tuples of affine expressions with optional conditions and
    3403             :  * add them up.
    3404             :  */
    3405           0 : __isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(
    3406             :         __isl_keep isl_stream *s)
    3407             : {
    3408             :         struct vars *v;
    3409             :         isl_set *dom;
    3410           0 :         isl_pw_multi_aff *pma = NULL;
    3411             : 
    3412           0 :         v = vars_new(s->ctx);
    3413           0 :         if (!v)
    3414           0 :                 return NULL;
    3415             : 
    3416           0 :         dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
    3417           0 :         if (next_is_tuple(s)) {
    3418           0 :                 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
    3419           0 :                 if (isl_stream_eat(s, ISL_TOKEN_TO))
    3420           0 :                         goto error;
    3421             :         }
    3422           0 :         if (isl_stream_eat(s, '{'))
    3423           0 :                 goto error;
    3424             : 
    3425           0 :         pma = read_conditional_multi_aff(s, isl_set_copy(dom), v);
    3426             : 
    3427           0 :         while (isl_stream_eat_if_available(s, ';')) {
    3428             :                 isl_pw_multi_aff *pma2;
    3429             : 
    3430           0 :                 pma2 = read_conditional_multi_aff(s, isl_set_copy(dom), v);
    3431           0 :                 pma = isl_pw_multi_aff_union_add(pma, pma2);
    3432           0 :                 if (!pma)
    3433           0 :                         goto error;
    3434             :         }
    3435             : 
    3436           0 :         if (isl_stream_eat(s, '}'))
    3437           0 :                 goto error;
    3438             : 
    3439           0 :         isl_set_free(dom);
    3440           0 :         vars_free(v);
    3441           0 :         return pma;
    3442             : error:
    3443           0 :         isl_pw_multi_aff_free(pma);
    3444           0 :         isl_set_free(dom);
    3445           0 :         vars_free(v);
    3446           0 :         return NULL;
    3447             : }
    3448             : 
    3449           0 : __isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
    3450             :         const char *str)
    3451             : {
    3452             :         isl_pw_multi_aff *pma;
    3453           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3454           0 :         if (!s)
    3455           0 :                 return NULL;
    3456           0 :         pma = isl_stream_read_pw_multi_aff(s);
    3457           0 :         isl_stream_free(s);
    3458           0 :         return pma;
    3459             : }
    3460             : 
    3461             : /* Read an isl_union_pw_multi_aff from "s".
    3462             :  * We currently read a generic object and if it turns out to be a set or
    3463             :  * a map, we convert that to an isl_union_pw_multi_aff.
    3464             :  * It would be more efficient if we were to construct
    3465             :  * the isl_union_pw_multi_aff directly.
    3466             :  */
    3467           0 : __isl_give isl_union_pw_multi_aff *isl_stream_read_union_pw_multi_aff(
    3468             :         __isl_keep isl_stream *s)
    3469             : {
    3470             :         struct isl_obj obj;
    3471             : 
    3472           0 :         obj = obj_read(s);
    3473           0 :         if (!obj.v)
    3474           0 :                 return NULL;
    3475             : 
    3476           0 :         if (obj.type == isl_obj_map || obj.type == isl_obj_set)
    3477           0 :                 obj = to_union(s->ctx, obj);
    3478           0 :         if (obj.type == isl_obj_union_map)
    3479           0 :                 return isl_union_pw_multi_aff_from_union_map(obj.v);
    3480           0 :         if (obj.type == isl_obj_union_set)
    3481           0 :                 return isl_union_pw_multi_aff_from_union_set(obj.v);
    3482             : 
    3483           0 :         obj.type->free(obj.v);
    3484           0 :         isl_die(s->ctx, isl_error_invalid, "unexpected object type",
    3485             :                 return NULL);
    3486             : }
    3487             : 
    3488             : /* Read an isl_union_pw_multi_aff from "str".
    3489             :  */
    3490           0 : __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_read_from_str(
    3491             :         isl_ctx *ctx, const char *str)
    3492             : {
    3493             :         isl_union_pw_multi_aff *upma;
    3494           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3495           0 :         if (!s)
    3496           0 :                 return NULL;
    3497           0 :         upma = isl_stream_read_union_pw_multi_aff(s);
    3498           0 :         isl_stream_free(s);
    3499           0 :         return upma;
    3500             : }
    3501             : 
    3502             : /* Assuming "pa" represents a single affine expression defined on a universe
    3503             :  * domain, extract this affine expression.
    3504             :  */
    3505           0 : static __isl_give isl_aff *aff_from_pw_aff(__isl_take isl_pw_aff *pa)
    3506             : {
    3507             :         isl_aff *aff;
    3508             : 
    3509           0 :         if (!pa)
    3510           0 :                 return NULL;
    3511           0 :         if (pa->n != 1)
    3512           0 :                 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
    3513             :                         "expecting single affine expression",
    3514             :                         goto error);
    3515           0 :         if (!isl_set_plain_is_universe(pa->p[0].set))
    3516           0 :                 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
    3517             :                         "expecting universe domain",
    3518             :                         goto error);
    3519             : 
    3520           0 :         aff = isl_aff_copy(pa->p[0].aff);
    3521           0 :         isl_pw_aff_free(pa);
    3522           0 :         return aff;
    3523             : error:
    3524           0 :         isl_pw_aff_free(pa);
    3525           0 :         return NULL;
    3526             : }
    3527             : 
    3528             : /* This function is called for each element in a tuple inside
    3529             :  * isl_stream_read_multi_val.
    3530             :  * Read an isl_val from "s" and add it to *list.
    3531             :  */
    3532           0 : static __isl_give isl_space *read_val_el(__isl_keep isl_stream *s,
    3533             :         struct vars *v, __isl_take isl_space *space, int rational, void *user)
    3534             : {
    3535           0 :         isl_val_list **list = (isl_val_list **) user;
    3536             :         isl_val *val;
    3537             : 
    3538           0 :         val = isl_stream_read_val(s);
    3539           0 :         *list = isl_val_list_add(*list, val);
    3540           0 :         if (!*list)
    3541           0 :                 return isl_space_free(space);
    3542             : 
    3543           0 :         return space;
    3544             : }
    3545             : 
    3546             : /* Read an isl_multi_val from "s".
    3547             :  *
    3548             :  * We first read a tuple space, collecting the element values in a list.
    3549             :  * Then we create an isl_multi_val from the space and the isl_val_list.
    3550             :  */
    3551           0 : __isl_give isl_multi_val *isl_stream_read_multi_val(__isl_keep isl_stream *s)
    3552             : {
    3553             :         struct vars *v;
    3554           0 :         isl_set *dom = NULL;
    3555             :         isl_space *space;
    3556           0 :         isl_multi_val *mv = NULL;
    3557             :         isl_val_list *list;
    3558             : 
    3559           0 :         v = vars_new(s->ctx);
    3560           0 :         if (!v)
    3561           0 :                 return NULL;
    3562             : 
    3563           0 :         dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
    3564           0 :         if (next_is_tuple(s)) {
    3565           0 :                 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
    3566           0 :                 if (isl_stream_eat(s, ISL_TOKEN_TO))
    3567           0 :                         goto error;
    3568             :         }
    3569           0 :         if (!isl_set_plain_is_universe(dom))
    3570           0 :                 isl_die(s->ctx, isl_error_invalid,
    3571             :                         "expecting universe parameter domain", goto error);
    3572           0 :         if (isl_stream_eat(s, '{'))
    3573           0 :                 goto error;
    3574             : 
    3575           0 :         space = isl_set_get_space(dom);
    3576             : 
    3577           0 :         list = isl_val_list_alloc(s->ctx, 0);
    3578           0 :         space = read_tuple_space(s, v, space, 1, 0, &read_val_el, &list);
    3579           0 :         mv = isl_multi_val_from_val_list(space, list);
    3580             : 
    3581           0 :         if (isl_stream_eat(s, '}'))
    3582           0 :                 goto error;
    3583             : 
    3584           0 :         vars_free(v);
    3585           0 :         isl_set_free(dom);
    3586           0 :         return mv;
    3587             : error:
    3588           0 :         vars_free(v);
    3589           0 :         isl_set_free(dom);
    3590           0 :         isl_multi_val_free(mv);
    3591           0 :         return NULL;
    3592             : }
    3593             : 
    3594             : /* Read an isl_multi_val from "str".
    3595             :  */
    3596           0 : __isl_give isl_multi_val *isl_multi_val_read_from_str(isl_ctx *ctx,
    3597             :         const char *str)
    3598             : {
    3599             :         isl_multi_val *mv;
    3600           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3601           0 :         if (!s)
    3602           0 :                 return NULL;
    3603           0 :         mv = isl_stream_read_multi_val(s);
    3604           0 :         isl_stream_free(s);
    3605           0 :         return mv;
    3606             : }
    3607             : 
    3608             : /* Read a multi-affine expression from "s".
    3609             :  * If the multi-affine expression has a domain, then the tuple
    3610             :  * representing this domain cannot involve any affine expressions.
    3611             :  * The tuple representing the actual expressions needs to consist
    3612             :  * of only affine expressions.  Moreover, these expressions can
    3613             :  * only depend on parameters and input dimensions and not on other
    3614             :  * output dimensions.
    3615             :  */
    3616           0 : __isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s)
    3617             : {
    3618             :         struct vars *v;
    3619           0 :         isl_set *dom = NULL;
    3620           0 :         isl_multi_pw_aff *tuple = NULL;
    3621             :         int dim, i, n;
    3622             :         isl_space *space, *dom_space;
    3623           0 :         isl_multi_aff *ma = NULL;
    3624             : 
    3625           0 :         v = vars_new(s->ctx);
    3626           0 :         if (!v)
    3627           0 :                 return NULL;
    3628             : 
    3629           0 :         dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
    3630           0 :         if (next_is_tuple(s)) {
    3631           0 :                 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
    3632           0 :                 if (isl_stream_eat(s, ISL_TOKEN_TO))
    3633           0 :                         goto error;
    3634             :         }
    3635           0 :         if (!isl_set_plain_is_universe(dom))
    3636           0 :                 isl_die(s->ctx, isl_error_invalid,
    3637             :                         "expecting universe parameter domain", goto error);
    3638           0 :         if (isl_stream_eat(s, '{'))
    3639           0 :                 goto error;
    3640             : 
    3641           0 :         tuple = read_tuple(s, v, 0, 0);
    3642           0 :         if (!tuple)
    3643           0 :                 goto error;
    3644           0 :         if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
    3645             :                 isl_set *set;
    3646             :                 isl_space *space;
    3647             :                 int has_expr;
    3648             : 
    3649           0 :                 has_expr = tuple_has_expr(tuple);
    3650           0 :                 if (has_expr < 0)
    3651           0 :                         goto error;
    3652           0 :                 if (has_expr)
    3653           0 :                         isl_die(s->ctx, isl_error_invalid,
    3654             :                                 "expecting universe domain", goto error);
    3655           0 :                 space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
    3656           0 :                 set = isl_set_universe(space);
    3657           0 :                 dom = isl_set_intersect_params(set, dom);
    3658           0 :                 isl_multi_pw_aff_free(tuple);
    3659           0 :                 tuple = read_tuple(s, v, 0, 0);
    3660           0 :                 if (!tuple)
    3661           0 :                         goto error;
    3662             :         }
    3663             : 
    3664           0 :         if (isl_stream_eat(s, '}'))
    3665           0 :                 goto error;
    3666             : 
    3667           0 :         n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
    3668           0 :         dim = isl_set_dim(dom, isl_dim_all);
    3669           0 :         dom_space = isl_set_get_space(dom);
    3670           0 :         space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
    3671           0 :         space = isl_space_align_params(space, isl_space_copy(dom_space));
    3672           0 :         if (!isl_space_is_params(dom_space))
    3673           0 :                 space = isl_space_map_from_domain_and_range(
    3674             :                                 isl_space_copy(dom_space), space);
    3675           0 :         isl_space_free(dom_space);
    3676           0 :         ma = isl_multi_aff_alloc(space);
    3677             : 
    3678           0 :         for (i = 0; i < n; ++i) {
    3679             :                 isl_pw_aff *pa;
    3680             :                 isl_aff *aff;
    3681           0 :                 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
    3682           0 :                 aff = aff_from_pw_aff(pa);
    3683           0 :                 if (!aff)
    3684           0 :                         goto error;
    3685           0 :                 if (isl_aff_involves_dims(aff, isl_dim_in, dim, i + 1)) {
    3686           0 :                         isl_aff_free(aff);
    3687           0 :                         isl_die(s->ctx, isl_error_invalid,
    3688             :                                 "not an affine expression", goto error);
    3689             :                 }
    3690           0 :                 aff = isl_aff_drop_dims(aff, isl_dim_in, dim, n);
    3691           0 :                 space = isl_multi_aff_get_domain_space(ma);
    3692           0 :                 aff = isl_aff_reset_domain_space(aff, space);
    3693           0 :                 ma = isl_multi_aff_set_aff(ma, i, aff);
    3694             :         }
    3695             : 
    3696           0 :         isl_multi_pw_aff_free(tuple);
    3697           0 :         vars_free(v);
    3698           0 :         isl_set_free(dom);
    3699           0 :         return ma;
    3700             : error:
    3701           0 :         isl_multi_pw_aff_free(tuple);
    3702           0 :         vars_free(v);
    3703           0 :         isl_set_free(dom);
    3704           0 :         isl_multi_aff_free(ma);
    3705           0 :         return NULL;
    3706             : }
    3707             : 
    3708           0 : __isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
    3709             :         const char *str)
    3710             : {
    3711             :         isl_multi_aff *maff;
    3712           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3713           0 :         if (!s)
    3714           0 :                 return NULL;
    3715           0 :         maff = isl_stream_read_multi_aff(s);
    3716           0 :         isl_stream_free(s);
    3717           0 :         return maff;
    3718             : }
    3719             : 
    3720             : /* Read an isl_multi_pw_aff from "s".
    3721             :  *
    3722             :  * The input format is similar to that of map, except that any conditions
    3723             :  * on the domains should be specified inside the tuple since each
    3724             :  * piecewise affine expression may have a different domain.
    3725             :  * However, additional, shared conditions can also be specified.
    3726             :  * This is especially useful for setting the explicit domain
    3727             :  * of a zero-dimensional isl_multi_pw_aff.
    3728             :  *
    3729             :  * Since we do not know in advance if the isl_multi_pw_aff lives
    3730             :  * in a set or a map space, we first read the first tuple and check
    3731             :  * if it is followed by a "->".  If so, we convert the tuple into
    3732             :  * the domain of the isl_multi_pw_aff and read in the next tuple.
    3733             :  * This tuple (or the first tuple if it was not followed by a "->")
    3734             :  * is then converted into the isl_multi_pw_aff through a call
    3735             :  * to extract_mpa_from_tuple and the domain of the result
    3736             :  * is intersected with the domain.
    3737             :  */
    3738           0 : __isl_give isl_multi_pw_aff *isl_stream_read_multi_pw_aff(
    3739             :         __isl_keep isl_stream *s)
    3740             : {
    3741             :         struct vars *v;
    3742           0 :         isl_set *dom = NULL;
    3743           0 :         isl_multi_pw_aff *tuple = NULL;
    3744           0 :         isl_multi_pw_aff *mpa = NULL;
    3745             : 
    3746           0 :         v = vars_new(s->ctx);
    3747           0 :         if (!v)
    3748           0 :                 return NULL;
    3749             : 
    3750           0 :         dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
    3751           0 :         if (next_is_tuple(s)) {
    3752           0 :                 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
    3753           0 :                 if (isl_stream_eat(s, ISL_TOKEN_TO))
    3754           0 :                         goto error;
    3755             :         }
    3756           0 :         if (isl_stream_eat(s, '{'))
    3757           0 :                 goto error;
    3758             : 
    3759           0 :         tuple = read_tuple(s, v, 0, 0);
    3760           0 :         if (!tuple)
    3761           0 :                 goto error;
    3762           0 :         if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
    3763           0 :                 isl_map *map = map_from_tuple(tuple, dom, isl_dim_in, v, 0);
    3764           0 :                 dom = isl_map_domain(map);
    3765           0 :                 tuple = read_tuple(s, v, 0, 0);
    3766           0 :                 if (!tuple)
    3767           0 :                         goto error;
    3768             :         }
    3769             : 
    3770           0 :         if (isl_stream_eat_if_available(s, ':'))
    3771           0 :                 dom = read_formula(s, v, dom, 0);
    3772             : 
    3773           0 :         if (isl_stream_eat(s, '}'))
    3774           0 :                 goto error;
    3775             : 
    3776           0 :         mpa = extract_mpa_from_tuple(isl_set_get_space(dom), tuple);
    3777             : 
    3778           0 :         isl_multi_pw_aff_free(tuple);
    3779           0 :         vars_free(v);
    3780           0 :         mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
    3781           0 :         return mpa;
    3782             : error:
    3783           0 :         isl_multi_pw_aff_free(tuple);
    3784           0 :         vars_free(v);
    3785           0 :         isl_set_free(dom);
    3786           0 :         isl_multi_pw_aff_free(mpa);
    3787           0 :         return NULL;
    3788             : }
    3789             : 
    3790             : /* Read an isl_multi_pw_aff from "str".
    3791             :  */
    3792           0 : __isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str(isl_ctx *ctx,
    3793             :         const char *str)
    3794             : {
    3795             :         isl_multi_pw_aff *mpa;
    3796           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3797           0 :         if (!s)
    3798           0 :                 return NULL;
    3799           0 :         mpa = isl_stream_read_multi_pw_aff(s);
    3800           0 :         isl_stream_free(s);
    3801           0 :         return mpa;
    3802             : }
    3803             : 
    3804             : /* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom".
    3805             :  */
    3806           0 : static __isl_give isl_union_pw_aff *read_union_pw_aff_with_dom(
    3807             :         __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v)
    3808             : {
    3809             :         isl_pw_aff *pa;
    3810           0 :         isl_union_pw_aff *upa = NULL;
    3811             :         isl_set *aff_dom;
    3812             :         int n;
    3813             : 
    3814           0 :         n = v->n;
    3815           0 :         aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
    3816           0 :         pa = read_pw_aff_with_dom(s, aff_dom, v);
    3817           0 :         vars_drop(v, v->n - n);
    3818             : 
    3819           0 :         upa = isl_union_pw_aff_from_pw_aff(pa);
    3820             : 
    3821           0 :         while (isl_stream_eat_if_available(s, ';')) {
    3822             :                 isl_pw_aff *pa_i;
    3823             :                 isl_union_pw_aff *upa_i;
    3824             : 
    3825           0 :                 n = v->n;
    3826           0 :                 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
    3827           0 :                 pa_i = read_pw_aff_with_dom(s, aff_dom, v);
    3828           0 :                 vars_drop(v, v->n - n);
    3829             : 
    3830           0 :                 upa_i = isl_union_pw_aff_from_pw_aff(pa_i);
    3831           0 :                 upa = isl_union_pw_aff_union_add(upa, upa_i);
    3832             :         }
    3833             : 
    3834           0 :         isl_set_free(dom);
    3835           0 :         return upa;
    3836             : }
    3837             : 
    3838             : /* Read an isl_union_pw_aff from "s".
    3839             :  *
    3840             :  * First check if there are any paramters, then read in the opening brace
    3841             :  * and use read_union_pw_aff_with_dom to read in the body of
    3842             :  * the isl_union_pw_aff.  Finally, read the closing brace.
    3843             :  */
    3844           0 : __isl_give isl_union_pw_aff *isl_stream_read_union_pw_aff(
    3845             :         __isl_keep isl_stream *s)
    3846             : {
    3847             :         struct vars *v;
    3848             :         isl_set *dom;
    3849           0 :         isl_union_pw_aff *upa = NULL;
    3850             : 
    3851           0 :         v = vars_new(s->ctx);
    3852           0 :         if (!v)
    3853           0 :                 return NULL;
    3854             : 
    3855           0 :         dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
    3856           0 :         if (next_is_tuple(s)) {
    3857           0 :                 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
    3858           0 :                 if (isl_stream_eat(s, ISL_TOKEN_TO))
    3859           0 :                         goto error;
    3860             :         }
    3861           0 :         if (isl_stream_eat(s, '{'))
    3862           0 :                 goto error;
    3863             : 
    3864           0 :         upa = read_union_pw_aff_with_dom(s, isl_set_copy(dom), v);
    3865             : 
    3866           0 :         if (isl_stream_eat(s, '}'))
    3867           0 :                 goto error;
    3868             : 
    3869           0 :         vars_free(v);
    3870           0 :         isl_set_free(dom);
    3871           0 :         return upa;
    3872             : error:
    3873           0 :         vars_free(v);
    3874           0 :         isl_set_free(dom);
    3875           0 :         isl_union_pw_aff_free(upa);
    3876           0 :         return NULL;
    3877             : }
    3878             : 
    3879             : /* Read an isl_union_pw_aff from "str".
    3880             :  */
    3881           0 : __isl_give isl_union_pw_aff *isl_union_pw_aff_read_from_str(isl_ctx *ctx,
    3882             :         const char *str)
    3883             : {
    3884             :         isl_union_pw_aff *upa;
    3885           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    3886           0 :         if (!s)
    3887           0 :                 return NULL;
    3888           0 :         upa = isl_stream_read_union_pw_aff(s);
    3889           0 :         isl_stream_free(s);
    3890           0 :         return upa;
    3891             : }
    3892             : 
    3893             : /* This function is called for each element in a tuple inside
    3894             :  * isl_stream_read_multi_union_pw_aff.
    3895             :  *
    3896             :  * Read a '{', the union piecewise affine expression body and a '}' and
    3897             :  * add the isl_union_pw_aff to *list.
    3898             :  */
    3899           0 : static __isl_give isl_space *read_union_pw_aff_el(__isl_keep isl_stream *s,
    3900             :         struct vars *v, __isl_take isl_space *space, int rational, void *user)
    3901             : {
    3902             :         isl_set *dom;
    3903             :         isl_union_pw_aff *upa;
    3904           0 :         isl_union_pw_aff_list **list = (isl_union_pw_aff_list **) user;
    3905             : 
    3906           0 :         dom = isl_set_universe(isl_space_params(isl_space_copy(space)));
    3907           0 :         if (isl_stream_eat(s, '{'))
    3908           0 :                 goto error;
    3909           0 :         upa = read_union_pw_aff_with_dom(s, dom, v);
    3910           0 :         *list = isl_union_pw_aff_list_add(*list, upa);
    3911           0 :         if (isl_stream_eat(s, '}'))
    3912           0 :                 return isl_space_free(space);
    3913           0 :         if (!*list)
    3914           0 :                 return isl_space_free(space);
    3915           0 :         return space;
    3916             : error:
    3917           0 :         isl_set_free(dom);
    3918           0 :         return isl_space_free(space);
    3919             : }
    3920             : 
    3921             : /* Do the next tokens in "s" correspond to an empty tuple?
    3922             :  * In particular, does the stream start with a '[', followed by a ']',
    3923             :  * not followed by a "->"?
    3924             :  */
    3925           0 : static int next_is_empty_tuple(__isl_keep isl_stream *s)
    3926             : {
    3927             :         struct isl_token *tok, *tok2, *tok3;
    3928           0 :         int is_empty_tuple = 0;
    3929             : 
    3930           0 :         tok = isl_stream_next_token(s);
    3931           0 :         if (!tok)
    3932           0 :                 return 0;
    3933           0 :         if (tok->type != '[') {
    3934           0 :                 isl_stream_push_token(s, tok);
    3935           0 :                 return 0;
    3936             :         }
    3937             : 
    3938           0 :         tok2 = isl_stream_next_token(s);
    3939           0 :         if (tok2 && tok2->type == ']') {
    3940           0 :                 tok3 = isl_stream_next_token(s);
    3941           0 :                 is_empty_tuple = !tok || tok->type != ISL_TOKEN_TO;
    3942           0 :                 if (tok3)
    3943           0 :                         isl_stream_push_token(s, tok3);
    3944             :         }
    3945           0 :         if (tok2)
    3946           0 :                 isl_stream_push_token(s, tok2);
    3947           0 :         isl_stream_push_token(s, tok);
    3948             : 
    3949           0 :         return is_empty_tuple;
    3950             : }
    3951             : 
    3952             : /* Do the next tokens in "s" correspond to a tuple of parameters?
    3953             :  * In particular, does the stream start with a '[' that is not
    3954             :  * followed by a '{' or a nested tuple?
    3955             :  */
    3956           0 : static int next_is_param_tuple(__isl_keep isl_stream *s)
    3957             : {
    3958             :         struct isl_token *tok, *tok2;
    3959             :         int is_tuple;
    3960             : 
    3961           0 :         tok = isl_stream_next_token(s);
    3962           0 :         if (!tok)
    3963           0 :                 return 0;
    3964           0 :         if (tok->type != '[' || next_is_tuple(s)) {
    3965           0 :                 isl_stream_push_token(s, tok);
    3966           0 :                 return 0;
    3967             :         }
    3968             : 
    3969           0 :         tok2 = isl_stream_next_token(s);
    3970           0 :         is_tuple = tok2 && tok2->type != '{';
    3971           0 :         if (tok2)
    3972           0 :                 isl_stream_push_token(s, tok2);
    3973           0 :         isl_stream_push_token(s, tok);
    3974             : 
    3975           0 :         return is_tuple;
    3976             : }
    3977             : 
    3978             : /* Read the core of a body of an isl_multi_union_pw_aff from "s",
    3979             :  * i.e., everything except the parameter specification and
    3980             :  * without shared domain constraints.
    3981             :  * "v" contains a description of the identifiers parsed so far.
    3982             :  * The parameters, if any, are specified by "space".
    3983             :  *
    3984             :  * The body is of the form
    3985             :  *
    3986             :  *      [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
    3987             :  *
    3988             :  * Read the tuple, collecting the individual isl_union_pw_aff
    3989             :  * elements in a list and construct the result from the tuple space and
    3990             :  * the list.
    3991             :  */
    3992           0 : static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body_core(
    3993             :         __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space)
    3994             : {
    3995             :         isl_union_pw_aff_list *list;
    3996             :         isl_multi_union_pw_aff *mupa;
    3997             : 
    3998           0 :         list = isl_union_pw_aff_list_alloc(s->ctx, 0);
    3999           0 :         space = read_tuple_space(s, v, space, 1, 0,
    4000             :                                 &read_union_pw_aff_el, &list);
    4001           0 :         mupa = isl_multi_union_pw_aff_from_union_pw_aff_list(space, list);
    4002             : 
    4003           0 :         return mupa;
    4004             : }
    4005             : 
    4006             : /* Read the body of an isl_union_set from "s",
    4007             :  * i.e., everything except the parameter specification.
    4008             :  * "v" contains a description of the identifiers parsed so far.
    4009             :  * The parameters, if any, are specified by "space".
    4010             :  *
    4011             :  * First read a generic disjunction of object bodies and then try and extract
    4012             :  * an isl_union_set from that.
    4013             :  */
    4014           0 : static __isl_give isl_union_set *read_union_set_body(__isl_keep isl_stream *s,
    4015             :         struct vars *v, __isl_take isl_space *space)
    4016             : {
    4017           0 :         struct isl_obj obj = { isl_obj_set, NULL };
    4018             :         isl_map *map;
    4019             : 
    4020           0 :         map = isl_set_universe(space);
    4021           0 :         if (isl_stream_eat(s, '{') < 0)
    4022           0 :                 goto error;
    4023           0 :         obj = obj_read_disjuncts(s, v, map);
    4024           0 :         if (isl_stream_eat(s, '}') < 0)
    4025           0 :                 goto error;
    4026           0 :         isl_map_free(map);
    4027             : 
    4028           0 :         return extract_union_set(s->ctx, obj);
    4029             : error:
    4030           0 :         obj.type->free(obj.v);
    4031           0 :         isl_map_free(map);
    4032           0 :         return NULL;
    4033             : }
    4034             : 
    4035             : /* Read the body of an isl_multi_union_pw_aff from "s",
    4036             :  * i.e., everything except the parameter specification.
    4037             :  * "v" contains a description of the identifiers parsed so far.
    4038             :  * The parameters, if any, are specified by "space".
    4039             :  *
    4040             :  * In particular, handle the special case with shared domain constraints.
    4041             :  * These are specified as
    4042             :  *
    4043             :  *      ([...] : ...)
    4044             :  *
    4045             :  * and are especially useful for setting the explicit domain
    4046             :  * of a zero-dimensional isl_multi_union_pw_aff.
    4047             :  * The core isl_multi_union_pw_aff body ([...]) is read by
    4048             :  * read_multi_union_pw_aff_body_core.
    4049             :  */
    4050           0 : static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body(
    4051             :         __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space)
    4052             : {
    4053             :         isl_multi_union_pw_aff *mupa;
    4054             : 
    4055           0 :         if (!isl_stream_next_token_is(s, '('))
    4056           0 :                 return read_multi_union_pw_aff_body_core(s, v, space);
    4057             : 
    4058           0 :         if (isl_stream_eat(s, '(') < 0)
    4059           0 :                 goto error;
    4060           0 :         mupa = read_multi_union_pw_aff_body_core(s, v, isl_space_copy(space));
    4061           0 :         if (isl_stream_eat_if_available(s, ':')) {
    4062             :                 isl_union_set *dom;
    4063             : 
    4064           0 :                 dom = read_union_set_body(s, v, space);
    4065           0 :                 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
    4066             :         } else {
    4067           0 :                 isl_space_free(space);
    4068             :         }
    4069           0 :         if (isl_stream_eat(s, ')') < 0)
    4070           0 :                 return isl_multi_union_pw_aff_free(mupa);
    4071             : 
    4072           0 :         return mupa;
    4073             : error:
    4074           0 :         isl_space_free(space);
    4075           0 :         return NULL;
    4076             : }
    4077             : 
    4078             : /* Read an isl_multi_union_pw_aff from "s".
    4079             :  *
    4080             :  * The input has the form
    4081             :  *
    4082             :  *      [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
    4083             :  *
    4084             :  * or
    4085             :  *
    4086             :  *      [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
    4087             :  *
    4088             :  * Additionally, a shared domain may be specified as
    4089             :  *
    4090             :  *      ([..] : ...)
    4091             :  *
    4092             :  * or
    4093             :  *
    4094             :  *      [..] -> ([..] : ...)
    4095             :  *
    4096             :  * The first case is handled by the caller, the second case
    4097             :  * is handled by read_multi_union_pw_aff_body.
    4098             :  *
    4099             :  * We first check for the special case of an empty tuple "[]".
    4100             :  * Then we check if there are any parameters.
    4101             :  * Finally, read the tuple and construct the result.
    4102             :  */
    4103           0 : static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_core(
    4104             :         __isl_keep isl_stream *s)
    4105             : {
    4106             :         struct vars *v;
    4107           0 :         isl_set *dom = NULL;
    4108             :         isl_space *space;
    4109           0 :         isl_multi_union_pw_aff *mupa = NULL;
    4110             : 
    4111           0 :         if (next_is_empty_tuple(s)) {
    4112           0 :                 if (isl_stream_eat(s, '['))
    4113           0 :                         return NULL;
    4114           0 :                 if (isl_stream_eat(s, ']'))
    4115           0 :                         return NULL;
    4116           0 :                 space = isl_space_set_alloc(s->ctx, 0, 0);
    4117           0 :                 return isl_multi_union_pw_aff_zero(space);
    4118             :         }
    4119             : 
    4120           0 :         v = vars_new(s->ctx);
    4121           0 :         if (!v)
    4122           0 :                 return NULL;
    4123             : 
    4124           0 :         dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
    4125           0 :         if (next_is_param_tuple(s)) {
    4126           0 :                 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
    4127           0 :                 if (isl_stream_eat(s, ISL_TOKEN_TO))
    4128           0 :                         goto error;
    4129             :         }
    4130           0 :         space = isl_set_get_space(dom);
    4131           0 :         isl_set_free(dom);
    4132           0 :         mupa = read_multi_union_pw_aff_body(s, v, space);
    4133             : 
    4134           0 :         vars_free(v);
    4135             : 
    4136           0 :         return mupa;
    4137             : error:
    4138           0 :         vars_free(v);
    4139           0 :         isl_set_free(dom);
    4140           0 :         isl_multi_union_pw_aff_free(mupa);
    4141           0 :         return NULL;
    4142             : }
    4143             : 
    4144             : /* Read an isl_multi_union_pw_aff from "s".
    4145             :  *
    4146             :  * In particular, handle the special case with shared domain constraints.
    4147             :  * These are specified as
    4148             :  *
    4149             :  *      ([...] : ...)
    4150             :  *
    4151             :  * and are especially useful for setting the explicit domain
    4152             :  * of a zero-dimensional isl_multi_union_pw_aff.
    4153             :  * The core isl_multi_union_pw_aff ([...]) is read by
    4154             :  * read_multi_union_pw_aff_core.
    4155             :  */
    4156           0 : __isl_give isl_multi_union_pw_aff *isl_stream_read_multi_union_pw_aff(
    4157             :         __isl_keep isl_stream *s)
    4158             : {
    4159             :         isl_multi_union_pw_aff *mupa;
    4160             : 
    4161           0 :         if (!isl_stream_next_token_is(s, '('))
    4162           0 :                 return read_multi_union_pw_aff_core(s);
    4163             : 
    4164           0 :         if (isl_stream_eat(s, '(') < 0)
    4165           0 :                 return NULL;
    4166           0 :         mupa = read_multi_union_pw_aff_core(s);
    4167           0 :         if (isl_stream_eat_if_available(s, ':')) {
    4168             :                 isl_union_set *dom;
    4169             : 
    4170           0 :                 dom = isl_stream_read_union_set(s);
    4171           0 :                 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
    4172             :         }
    4173           0 :         if (isl_stream_eat(s, ')') < 0)
    4174           0 :                 return isl_multi_union_pw_aff_free(mupa);
    4175           0 :         return mupa;
    4176             : }
    4177             : 
    4178             : /* Read an isl_multi_union_pw_aff from "str".
    4179             :  */
    4180           0 : __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_read_from_str(
    4181             :         isl_ctx *ctx, const char *str)
    4182             : {
    4183             :         isl_multi_union_pw_aff *mupa;
    4184           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    4185           0 :         if (!s)
    4186           0 :                 return NULL;
    4187           0 :         mupa = isl_stream_read_multi_union_pw_aff(s);
    4188           0 :         isl_stream_free(s);
    4189           0 :         return mupa;
    4190             : }
    4191             : 
    4192           0 : __isl_give isl_union_pw_qpolynomial *isl_stream_read_union_pw_qpolynomial(
    4193             :         __isl_keep isl_stream *s)
    4194             : {
    4195             :         struct isl_obj obj;
    4196             : 
    4197           0 :         obj = obj_read(s);
    4198           0 :         if (obj.type == isl_obj_pw_qpolynomial) {
    4199           0 :                 obj.type = isl_obj_union_pw_qpolynomial;
    4200           0 :                 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
    4201             :         }
    4202           0 :         if (obj.v)
    4203           0 :                 isl_assert(s->ctx, obj.type == isl_obj_union_pw_qpolynomial,
    4204             :                            goto error);
    4205             : 
    4206           0 :         return obj.v;
    4207             : error:
    4208           0 :         obj.type->free(obj.v);
    4209           0 :         return NULL;
    4210             : }
    4211             : 
    4212           0 : __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_read_from_str(
    4213             :         isl_ctx *ctx, const char *str)
    4214             : {
    4215             :         isl_union_pw_qpolynomial *upwqp;
    4216           0 :         isl_stream *s = isl_stream_new_str(ctx, str);
    4217           0 :         if (!s)
    4218           0 :                 return NULL;
    4219           0 :         upwqp = isl_stream_read_union_pw_qpolynomial(s);
    4220           0 :         isl_stream_free(s);
    4221           0 :         return upwqp;
    4222             : }

Generated by: LCOV version 1.12