+static int is_comparator(struct isl_token *tok)
+{
+ if (!tok)
+ return 0;
+
+ switch (tok->type) {
+ case ISL_TOKEN_LT:
+ case ISL_TOKEN_GT:
+ case ISL_TOKEN_LE:
+ case ISL_TOKEN_GE:
+ case ISL_TOKEN_NE:
+ case '=':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static struct isl_map *read_disjuncts(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map);
+static __isl_give isl_pw_aff *accept_extended_affine(struct isl_stream *s,
+ __isl_take isl_space *dim, struct vars *v);
+
+/* Accept a ternary operator, given the first argument.
+ */
+static __isl_give isl_pw_aff *accept_ternary(struct isl_stream *s,
+ __isl_take isl_map *cond, struct vars *v)
+{
+ isl_space *dim;
+ isl_pw_aff *pwaff1 = NULL, *pwaff2 = NULL;
+
+ if (!cond)
+ return NULL;
+
+ if (isl_stream_eat(s, '?'))
+ goto error;
+
+ dim = isl_space_wrap(isl_map_get_space(cond));
+ pwaff1 = accept_extended_affine(s, dim, v);
+ if (!pwaff1)
+ goto error;
+
+ if (isl_stream_eat(s, ':'))
+ goto error;
+
+ pwaff2 = accept_extended_affine(s, isl_pw_aff_get_space(pwaff1), v);
+ if (!pwaff1)
+ goto error;
+
+ return isl_pw_aff_cond(isl_map_wrap(cond), pwaff1, pwaff2);
+error:
+ isl_map_free(cond);
+ isl_pw_aff_free(pwaff1);
+ isl_pw_aff_free(pwaff2);
+ return NULL;
+}
+
+/* Accept an affine expression that may involve ternary operators.
+ * We first read an affine expression.
+ * If it is not followed by a comparison operator, we simply return it.
+ * Otherwise, we assume the affine epxression is part of the first
+ * argument of a ternary operator and try to parse that.
+ */
+static __isl_give isl_pw_aff *accept_extended_affine(struct isl_stream *s,
+ __isl_take isl_space *dim, struct vars *v)
+{
+ isl_map *cond;
+ isl_pw_aff *pwaff;
+ struct isl_token *tok;
+ int line = -1, col = -1;
+ int is_comp;
+
+ tok = isl_stream_next_token(s);
+ if (tok) {
+ line = tok->line;
+ col = tok->col;
+ isl_stream_push_token(s, tok);
+ }
+
+ pwaff = accept_affine(s, dim, v);
+ if (!pwaff)
+ return NULL;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return isl_pw_aff_free(pwaff);
+
+ is_comp = is_comparator(tok);
+ isl_stream_push_token(s, tok);
+ if (!is_comp)
+ return pwaff;
+
+ tok = isl_token_new(s->ctx, line, col, 0);
+ if (!tok)
+ return isl_pw_aff_free(pwaff);
+ tok->type = ISL_TOKEN_AFF;
+ tok->u.pwaff = pwaff;
+
+ cond = isl_map_universe(isl_space_unwrap(isl_pw_aff_get_space(pwaff)));
+
+ isl_stream_push_token(s, tok);
+
+ cond = read_disjuncts(s, v, cond);
+
+ return accept_ternary(s, cond, v);
+}
+