Polly 20.0.0git
isl_stream.c
Go to the documentation of this file.
1/*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 *
4 * Use of this software is governed by the MIT license
5 *
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8 */
9
10#include <ctype.h>
11#include <string.h>
12#include <isl_ctx_private.h>
13#include <isl_stream_private.h>
14#include <isl/map.h>
15#include <isl/aff.h>
16#include <isl_val_private.h>
17#include <isl_options_private.h>
18
20 char *name;
22};
23
24static isl_bool same_name(const void *entry, const void *val)
25{
26 const struct isl_keyword *keyword = (const struct isl_keyword *)entry;
27
28 return isl_bool_ok(!strcmp(keyword->name, val));
29}
30
32 const char *name)
33{
34 struct isl_hash_table_entry *entry;
35 struct isl_keyword *keyword;
36 uint32_t name_hash;
37
38 if (!s->keywords) {
39 s->keywords = isl_hash_table_alloc(s->ctx, 10);
40 if (!s->keywords)
41 return ISL_TOKEN_ERROR;
42 s->next_type = ISL_TOKEN_LAST;
43 }
44
45 name_hash = isl_hash_string(isl_hash_init(), name);
46
47 entry = isl_hash_table_find(s->ctx, s->keywords, name_hash,
48 same_name, name, 1);
49 if (!entry)
50 return ISL_TOKEN_ERROR;
51 if (entry->data) {
52 keyword = entry->data;
53 return keyword->type;
54 }
55
56 keyword = isl_calloc_type(s->ctx, struct isl_keyword);
57 if (!keyword)
58 return ISL_TOKEN_ERROR;
59 keyword->type = s->next_type++;
60 keyword->name = strdup(name);
61 if (!keyword->name) {
62 free(keyword);
63 return ISL_TOKEN_ERROR;
64 }
65 entry->data = keyword;
66
67 return keyword->type;
68}
69
71 int line, int col, unsigned on_new_line)
72{
73 struct isl_token *tok = isl_alloc_type(ctx, struct isl_token);
74 if (!tok)
75 return NULL;
76 tok->line = line;
77 tok->col = col;
79 tok->is_keyword = 0;
80 tok->u.s = NULL;
81 return tok;
82}
83
84/* Return the type of "tok".
85 */
87{
88 return tok ? tok->type : ISL_TOKEN_ERROR;
89}
90
91/* Given a token of type ISL_TOKEN_VALUE, return the value it represents.
92 */
94{
95 if (!tok)
96 return NULL;
97 if (tok->type != ISL_TOKEN_VALUE)
98 isl_die(ctx, isl_error_invalid, "not a value token",
99 return NULL);
100
101 return isl_val_int_from_isl_int(ctx, tok->u.v);
102}
103
104/* Does the given token have a string representation?
105 */
107{
108 if (!tok)
109 return isl_bool_error;
110 return isl_bool_ok(tok->u.s != NULL);
111}
112
113/* Given a token with a string representation, return a copy of this string.
114 */
116{
117 if (!tok)
118 return NULL;
119 if (!tok->u.s)
121 "token does not have a string representation",
122 return NULL);
123
124 return strdup(tok->u.s);
125}
126
127void isl_token_free(struct isl_token *tok)
128{
129 if (!tok)
130 return;
131 if (tok->type == ISL_TOKEN_VALUE)
132 isl_int_clear(tok->u.v);
133 else if (tok->type == ISL_TOKEN_MAP)
134 isl_map_free(tok->u.map);
135 else if (tok->type == ISL_TOKEN_AFF)
136 isl_pw_aff_free(tok->u.pwaff);
137 else
138 free(tok->u.s);
139 free(tok);
140}
141
143 char *msg)
144{
145 int line = tok ? tok->line : s->line;
146 int col = tok ? tok->col : s->col;
147
148 isl_ctx_set_full_error(s->ctx, isl_error_invalid, "syntax error",
149 __FILE__, __LINE__);
150
151 if (s->ctx->opt->on_error == ISL_ON_ERROR_CONTINUE)
152 return;
153 fprintf(stderr, "syntax error (%d, %d): %s\n", line, col, msg);
154 if (tok) {
155 if (tok->type < 256)
156 fprintf(stderr, "got '%c'\n", tok->type);
157 else if (tok->type == ISL_TOKEN_IDENT)
158 fprintf(stderr, "got ident '%s'\n", tok->u.s);
159 else if (tok->is_keyword)
160 fprintf(stderr, "got keyword '%s'\n", tok->u.s);
161 else if (tok->type == ISL_TOKEN_VALUE) {
162 fprintf(stderr, "got value '");
163 isl_int_print(stderr, tok->u.v, 0);
164 fprintf(stderr, "'\n");
165 } else if (tok->type == ISL_TOKEN_MAP) {
166 isl_printer *p;
167 fprintf(stderr, "got map '");
168 p = isl_printer_to_file(s->ctx, stderr);
169 p = isl_printer_print_map(p, tok->u.map);
171 fprintf(stderr, "'\n");
172 } else if (tok->type == ISL_TOKEN_AFF) {
173 isl_printer *p;
174 fprintf(stderr, "got affine expression '");
175 p = isl_printer_to_file(s->ctx, stderr);
178 fprintf(stderr, "'\n");
179 } else if (tok->u.s)
180 fprintf(stderr, "got token '%s'\n", tok->u.s);
181 else
182 fprintf(stderr, "got token type %d\n", tok->type);
183 }
184 if (s->ctx->opt->on_error == ISL_ON_ERROR_ABORT)
185 abort();
186}
187
189{
190 int i;
191 isl_stream *s = isl_calloc_type(ctx, struct isl_stream);
192 if (!s)
193 return NULL;
194 s->ctx = ctx;
195 isl_ctx_ref(s->ctx);
196 s->file = NULL;
197 s->str = NULL;
198 s->len = 0;
199 s->line = 1;
200 s->col = 1;
201 s->eof = 0;
202 s->last_line = 0;
203 s->c = -1;
204 s->n_un = 0;
205 for (i = 0; i < 5; ++i)
206 s->tokens[i] = NULL;
207 s->n_token = 0;
208 s->keywords = NULL;
209 s->size = 256;
210 s->buffer = isl_alloc_array(ctx, char, s->size);
211 if (!s->buffer)
212 goto error;
213 return s;
214error:
216 return NULL;
217}
218
220{
222 if (!s)
223 return NULL;
224 s->file = file;
225 return s;
226}
227
229{
230 isl_stream *s;
231 if (!str)
232 return NULL;
233 s = isl_stream_new(ctx);
234 if (!s)
235 return NULL;
236 s->str = str;
237 return s;
238}
239
240/* Read a character from the stream and advance s->line and s->col
241 * to point to the next character.
242 */
244{
245 int c;
246 if (s->eof)
247 return -1;
248 if (s->n_un)
249 return s->c = s->un[--s->n_un];
250 if (s->file)
251 c = fgetc(s->file);
252 else {
253 c = *s->str++;
254 if (c == '\0')
255 c = -1;
256 }
257 if (c == -1)
258 s->eof = 1;
259 else if (c == '\n') {
260 s->line++;
261 s->col = 1;
262 } else
263 s->col++;
264 s->c = c;
265 return c;
266}
267
269{
270 isl_assert(s->ctx, s->n_un < 5, return);
271 s->un[s->n_un++] = c;
272 s->c = -1;
273}
274
275/* Read a character from the stream, skipping pairs of '\\' and '\n'.
276 * Set s->start_line and s->start_col to the line and column
277 * of the returned character.
278 */
280{
281 int c;
282
283 do {
284 s->start_line = s->line;
285 s->start_col = s->col;
286 c = stream_getc(s);
287 if (c != '\\')
288 return c;
289 c = stream_getc(s);
290 } while (c == '\n');
291
293
294 return '\\';
295}
296
298{
299 if (s->len >= s->size) {
300 char *buffer;
301 s->size = (3*s->size)/2;
302 buffer = isl_realloc_array(s->ctx, s->buffer, char, s->size);
303 if (!buffer)
304 return -1;
305 s->buffer = buffer;
306 }
307 s->buffer[s->len++] = c;
308 return 0;
309}
310
312{
313 isl_assert(s->ctx, s->n_token < 5, return);
314 s->tokens[s->n_token++] = tok;
315}
316
318{
319 struct isl_hash_table_entry *entry;
320 struct isl_keyword *keyword;
321 uint32_t name_hash;
322
323 if (!strcasecmp(s->buffer, "exists"))
324 return ISL_TOKEN_EXISTS;
325 if (!strcasecmp(s->buffer, "and"))
326 return ISL_TOKEN_AND;
327 if (!strcasecmp(s->buffer, "or"))
328 return ISL_TOKEN_OR;
329 if (!strcasecmp(s->buffer, "implies"))
330 return ISL_TOKEN_IMPLIES;
331 if (!strcasecmp(s->buffer, "not"))
332 return ISL_TOKEN_NOT;
333 if (!strcasecmp(s->buffer, "infty"))
334 return ISL_TOKEN_INFTY;
335 if (!strcasecmp(s->buffer, "infinity"))
336 return ISL_TOKEN_INFTY;
337 if (!strcasecmp(s->buffer, "NaN"))
338 return ISL_TOKEN_NAN;
339 if (!strcasecmp(s->buffer, "min"))
340 return ISL_TOKEN_MIN;
341 if (!strcasecmp(s->buffer, "max"))
342 return ISL_TOKEN_MAX;
343 if (!strcasecmp(s->buffer, "rat"))
344 return ISL_TOKEN_RAT;
345 if (!strcasecmp(s->buffer, "true"))
346 return ISL_TOKEN_TRUE;
347 if (!strcasecmp(s->buffer, "false"))
348 return ISL_TOKEN_FALSE;
349 if (!strcasecmp(s->buffer, "ceild"))
350 return ISL_TOKEN_CEILD;
351 if (!strcasecmp(s->buffer, "floord"))
352 return ISL_TOKEN_FLOORD;
353 if (!strcasecmp(s->buffer, "mod"))
354 return ISL_TOKEN_MOD;
355 if (!strcasecmp(s->buffer, "ceil"))
356 return ISL_TOKEN_CEIL;
357 if (!strcasecmp(s->buffer, "floor"))
358 return ISL_TOKEN_FLOOR;
359
360 if (!s->keywords)
361 return ISL_TOKEN_IDENT;
362
363 name_hash = isl_hash_string(isl_hash_init(), s->buffer);
364 entry = isl_hash_table_find(s->ctx, s->keywords, name_hash, same_name,
365 s->buffer, 0);
366 if (!entry)
367 return ISL_TOKEN_ERROR;
368 if (entry != isl_hash_table_entry_none) {
369 keyword = entry->data;
370 return keyword->type;
371 }
372
373 return ISL_TOKEN_IDENT;
374}
375
377{
378 int c;
379
380 while ((c = isl_stream_getc(s)) != -1 && c != '\n')
381 /* nothing */
382 ;
383
384 return c == -1 ? -1 : 0;
385}
386
387static struct isl_token *next_token(__isl_keep isl_stream *s, int same_line)
388{
389 int c;
390 struct isl_token *tok = NULL;
391 int line, col;
392 int old_line = s->last_line;
393
394 if (s->n_token) {
395 if (same_line && s->tokens[s->n_token - 1]->on_new_line)
396 return NULL;
397 return s->tokens[--s->n_token];
398 }
399
400 if (same_line && s->c == '\n')
401 return NULL;
402
403 s->len = 0;
404
405 /* skip spaces and comment lines */
406 while ((c = isl_stream_getc(s)) != -1) {
407 if (c == '#') {
408 if (isl_stream_skip_line(s) < 0)
409 break;
410 c = '\n';
411 if (same_line)
412 break;
413 } else if (!isspace(c) || (same_line && c == '\n'))
414 break;
415 }
416
417 line = s->start_line;
418 col = s->start_col;
419
420 if (c == -1 || (same_line && c == '\n'))
421 return NULL;
422 s->last_line = line;
423
424 if (c == '(' ||
425 c == ')' ||
426 c == '+' ||
427 c == '*' ||
428 c == '%' ||
429 c == '?' ||
430 c == '^' ||
431 c == '@' ||
432 c == '$' ||
433 c == ',' ||
434 c == '.' ||
435 c == ';' ||
436 c == '[' ||
437 c == ']' ||
438 c == '{' ||
439 c == '}') {
440 tok = isl_token_new(s->ctx, line, col, old_line != line);
441 if (!tok)
442 return NULL;
443 tok->type = (enum isl_token_type)c;
444 return tok;
445 }
446 if (c == '-') {
447 int c;
448 if ((c = isl_stream_getc(s)) == '>') {
449 tok = isl_token_new(s->ctx, line, col, old_line != line);
450 if (!tok)
451 return NULL;
452 tok->u.s = strdup("->");
453 tok->type = ISL_TOKEN_TO;
454 return tok;
455 }
456 if (c != -1)
458 tok = isl_token_new(s->ctx, line, col, old_line != line);
459 if (!tok)
460 return NULL;
461 tok->type = (enum isl_token_type) '-';
462 return tok;
463 }
464 if (isdigit(c)) {
465 int minus = c == '-';
466 tok = isl_token_new(s->ctx, line, col, old_line != line);
467 if (!tok)
468 return NULL;
469 tok->type = ISL_TOKEN_VALUE;
470 isl_int_init(tok->u.v);
471 if (isl_stream_push_char(s, c))
472 goto error;
473 while ((c = isl_stream_getc(s)) != -1 && isdigit(c))
474 if (isl_stream_push_char(s, c))
475 goto error;
476 if (c != -1)
478 isl_stream_push_char(s, '\0');
479 isl_int_read(tok->u.v, s->buffer);
480 if (minus && isl_int_is_zero(tok->u.v)) {
481 tok->col++;
482 tok->on_new_line = 0;
484 tok = isl_token_new(s->ctx, line, col, old_line != line);
485 if (!tok)
486 return NULL;
487 tok->type = (enum isl_token_type) '-';
488 }
489 return tok;
490 }
491 if (isalpha(c) || c == '_') {
492 tok = isl_token_new(s->ctx, line, col, old_line != line);
493 if (!tok)
494 return NULL;
496 while ((c = isl_stream_getc(s)) != -1 &&
497 (isalnum(c) || c == '_'))
499 if (c != -1)
501 while ((c = isl_stream_getc(s)) != -1 && c == '\'')
503 if (c != -1)
505 isl_stream_push_char(s, '\0');
506 tok->type = check_keywords(s);
507 if (tok->type != ISL_TOKEN_IDENT)
508 tok->is_keyword = 1;
509 tok->u.s = strdup(s->buffer);
510 if (!tok->u.s)
511 goto error;
512 return tok;
513 }
514 if (c == '"') {
515 tok = isl_token_new(s->ctx, line, col, old_line != line);
516 if (!tok)
517 return NULL;
518 tok->type = ISL_TOKEN_STRING;
519 tok->u.s = NULL;
520 while ((c = isl_stream_getc(s)) != -1 && c != '"' && c != '\n')
522 if (c != '"') {
523 isl_stream_error(s, NULL, "unterminated string");
524 goto error;
525 }
526 isl_stream_push_char(s, '\0');
527 tok->u.s = strdup(s->buffer);
528 return tok;
529 }
530 if (c == '=') {
531 int c;
532 tok = isl_token_new(s->ctx, line, col, old_line != line);
533 if (!tok)
534 return NULL;
535 if ((c = isl_stream_getc(s)) == '=') {
536 tok->u.s = strdup("==");
537 tok->type = ISL_TOKEN_EQ_EQ;
538 return tok;
539 }
540 if (c != -1)
542 tok->type = (enum isl_token_type) '=';
543 return tok;
544 }
545 if (c == ':') {
546 int c;
547 tok = isl_token_new(s->ctx, line, col, old_line != line);
548 if (!tok)
549 return NULL;
550 if ((c = isl_stream_getc(s)) == '=') {
551 tok->u.s = strdup(":=");
552 tok->type = ISL_TOKEN_DEF;
553 return tok;
554 }
555 if (c != -1)
557 tok->type = (enum isl_token_type) ':';
558 return tok;
559 }
560 if (c == '>') {
561 int c;
562 tok = isl_token_new(s->ctx, line, col, old_line != line);
563 if (!tok)
564 return NULL;
565 if ((c = isl_stream_getc(s)) == '=') {
566 tok->u.s = strdup(">=");
567 tok->type = ISL_TOKEN_GE;
568 return tok;
569 } else if (c == '>') {
570 if ((c = isl_stream_getc(s)) == '=') {
571 tok->u.s = strdup(">>=");
572 tok->type = ISL_TOKEN_LEX_GE;
573 return tok;
574 }
575 tok->u.s = strdup(">>");
576 tok->type = ISL_TOKEN_LEX_GT;
577 } else {
578 tok->u.s = strdup(">");
579 tok->type = ISL_TOKEN_GT;
580 }
581 if (c != -1)
583 return tok;
584 }
585 if (c == '<') {
586 int c;
587 tok = isl_token_new(s->ctx, line, col, old_line != line);
588 if (!tok)
589 return NULL;
590 if ((c = isl_stream_getc(s)) == '=') {
591 tok->u.s = strdup("<=");
592 tok->type = ISL_TOKEN_LE;
593 return tok;
594 } else if (c == '<') {
595 if ((c = isl_stream_getc(s)) == '=') {
596 tok->u.s = strdup("<<=");
597 tok->type = ISL_TOKEN_LEX_LE;
598 return tok;
599 }
600 tok->u.s = strdup("<<");
601 tok->type = ISL_TOKEN_LEX_LT;
602 } else {
603 tok->u.s = strdup("<");
604 tok->type = ISL_TOKEN_LT;
605 }
606 if (c != -1)
608 return tok;
609 }
610 if (c == '&') {
611 tok = isl_token_new(s->ctx, line, col, old_line != line);
612 if (!tok)
613 return NULL;
614 tok->type = ISL_TOKEN_AND;
615 if ((c = isl_stream_getc(s)) != '&' && c != -1) {
616 tok->u.s = strdup("&");
618 } else
619 tok->u.s = strdup("&&");
620 return tok;
621 }
622 if (c == '|') {
623 tok = isl_token_new(s->ctx, line, col, old_line != line);
624 if (!tok)
625 return NULL;
626 tok->type = ISL_TOKEN_OR;
627 if ((c = isl_stream_getc(s)) != '|' && c != -1) {
628 tok->u.s = strdup("|");
630 } else
631 tok->u.s = strdup("||");
632 return tok;
633 }
634 if (c == '/') {
635 tok = isl_token_new(s->ctx, line, col, old_line != line);
636 if (!tok)
637 return NULL;
638 if ((c = isl_stream_getc(s)) == '\\') {
639 tok->u.s = strdup("/\\");
640 tok->type = ISL_TOKEN_AND;
641 return tok;
642 } else if (c == '/') {
643 tok->u.s = strdup("//");
644 tok->type = ISL_TOKEN_INT_DIV;
645 return tok;
646 } else {
647 tok->type = (enum isl_token_type) '/';
648 }
649 if (c != -1)
651 return tok;
652 }
653 if (c == '\\') {
654 tok = isl_token_new(s->ctx, line, col, old_line != line);
655 if (!tok)
656 return NULL;
657 if ((c = isl_stream_getc(s)) != '/' && c != -1) {
658 tok->type = (enum isl_token_type) '\\';
660 } else {
661 tok->u.s = strdup("\\/");
662 tok->type = ISL_TOKEN_OR;
663 }
664 return tok;
665 }
666 if (c == '!') {
667 tok = isl_token_new(s->ctx, line, col, old_line != line);
668 if (!tok)
669 return NULL;
670 if ((c = isl_stream_getc(s)) == '=') {
671 tok->u.s = strdup("!=");
672 tok->type = ISL_TOKEN_NE;
673 return tok;
674 } else {
675 tok->type = ISL_TOKEN_NOT;
676 tok->u.s = strdup("!");
677 }
678 if (c != -1)
680 return tok;
681 }
682
683 tok = isl_token_new(s->ctx, line, col, old_line != line);
684 if (!tok)
685 return NULL;
686 tok->type = ISL_TOKEN_UNKNOWN;
687 return tok;
688error:
689 isl_token_free(tok);
690 return NULL;
691}
692
694{
695 return next_token(s, 0);
696}
697
699{
700 return next_token(s, 1);
701}
702
704{
705 struct isl_token *tok;
706
708 if (!tok)
709 return 0;
710 if (tok->type == type) {
711 isl_token_free(tok);
712 return 1;
713 }
715 return 0;
716}
717
719{
720 struct isl_token *tok;
721 int r;
722
724 if (!tok)
725 return 0;
726 r = tok->type == type;
728 return r;
729}
730
732{
733 struct isl_token *tok;
734
736 if (!tok)
737 return NULL;
738 if (tok->type == ISL_TOKEN_IDENT) {
739 char *ident = strdup(tok->u.s);
740 isl_token_free(tok);
741 return ident;
742 }
744 return NULL;
745}
746
748{
749 struct isl_token *tok;
750
752 if (!tok) {
753 if (s->eof)
754 isl_stream_error(s, NULL, "unexpected EOF");
755 return -1;
756 }
757 if (tok->type == type) {
758 isl_token_free(tok);
759 return 0;
760 }
761 isl_stream_error(s, tok, "expecting other token");
762 isl_token_free(tok);
763 return -1;
764}
765
767{
768 struct isl_token *tok;
769
771
772 if (!tok)
773 return 1;
774
776 return 0;
777}
778
779static isl_stat free_keyword(void **p, void *user)
780{
781 struct isl_keyword *keyword = *p;
782
783 free(keyword->name);
784 free(keyword);
785
786 return isl_stat_ok;
787}
788
790{
791 int i;
792
793 if (!s)
794 return;
795 for (i = 0; i < s->n_token; ++i)
796 isl_token_free(s->tokens[i]);
797 s->n_token = 0;
798}
799
801{
802 return s ? s->ctx : NULL;
803}
804
806{
807 if (!s)
808 return;
809 free(s->buffer);
810 if (s->n_token != 0) {
811 struct isl_token *tok = isl_stream_next_token(s);
812 isl_stream_error(s, tok, "unexpected token");
813 isl_token_free(tok);
814 }
815 if (s->keywords) {
816 isl_hash_table_foreach(s->ctx, s->keywords, &free_keyword, NULL);
817 isl_hash_table_free(s->ctx, s->keywords);
818 }
819 free(s->yaml_state);
820 free(s->yaml_indent);
821 isl_ctx_deref(s->ctx);
822 free(s);
823}
824
825/* Push "state" onto the stack of currently active YAML elements.
826 * The caller is responsible for setting the corresponding indentation.
827 * Return 0 on success and -1 on failure.
828 */
830{
831 if (s->yaml_size < s->yaml_depth + 1) {
832 int *indent;
833 enum isl_yaml_state *state;
834
835 state = isl_realloc_array(s->ctx, s->yaml_state,
836 enum isl_yaml_state, s->yaml_depth + 1);
837 if (!state)
838 return -1;
839 s->yaml_state = state;
840
841 indent = isl_realloc_array(s->ctx, s->yaml_indent,
842 int, s->yaml_depth + 1);
843 if (!indent)
844 return -1;
845 s->yaml_indent = indent;
846
847 s->yaml_size = s->yaml_depth + 1;
848 }
849
850 s->yaml_state[s->yaml_depth] = state;
851 s->yaml_depth++;
852
853 return 0;
854}
855
856/* Remove the innermost active YAML element from the stack.
857 * Return isl_stat_ok on success and isl_stat_error on failure.
858 */
860{
861 if (!s)
862 return isl_stat_error;
863 if (s->yaml_depth < 1)
865 "not in YAML construct", return isl_stat_error);
866
867 s->yaml_depth--;
868
869 return isl_stat_ok;
870}
871
872/* Set the state of the innermost active YAML element to "state".
873 * Return 0 on success and -1 on failure.
874 */
876{
877 if (!s)
878 return -1;
879 if (s->yaml_depth < 1)
881 "not in YAML construct", return -1);
882
883 s->yaml_state[s->yaml_depth - 1] = state;
884
885 return 0;
886}
887
888/* Return the state of the innermost active YAML element.
889 * Return isl_yaml_none if we are not inside any YAML element.
890 */
892{
893 if (!s)
894 return isl_yaml_none;
895 if (s->yaml_depth < 1)
896 return isl_yaml_none;
897 return s->yaml_state[s->yaml_depth - 1];
898}
899
900/* Set the indentation of the innermost active YAML element to "indent".
901 * If "indent" is equal to ISL_YAML_INDENT_FLOW, then this means
902 * that the current element is in flow format.
903 */
905{
906 if (s->yaml_depth < 1)
908 "not in YAML element", return isl_stat_error);
909
910 s->yaml_indent[s->yaml_depth - 1] = indent;
911
912 return isl_stat_ok;
913}
914
915/* Return the indentation of the innermost active YAML element
916 * of -1 on error.
917 */
919{
920 if (s->yaml_depth < 1)
922 "not in YAML element", return -1);
923
924 return s->yaml_indent[s->yaml_depth - 1];
925}
926
927/* Move to the next state at the innermost level.
928 * Return isl_bool_true if successful.
929 * Return isl_bool_false if we are at the end of the innermost level.
930 * Return isl_bool_error on error.
931 *
932 * If we are in state isl_yaml_mapping_key_start, then we have just
933 * started a mapping and we are expecting a key. If the mapping started
934 * with a '{', then we check if the next token is a '}'. If so,
935 * then the mapping is empty and there is no next state at this level.
936 * Otherwise, we assume that there is at least one key (the one from
937 * which we derived the indentation in isl_stream_yaml_read_start_mapping.
938 *
939 * If we are in state isl_yaml_mapping_key, then the we expect a colon
940 * followed by a value, so there is always a next state unless
941 * some error occurs.
942 *
943 * If we are in state isl_yaml_mapping_val, then there may or may
944 * not be a subsequent key in the same mapping.
945 * In flow format, the next key is preceded by a comma.
946 * In block format, the next key has the same indentation as the first key.
947 * If the first token has a smaller indentation, then we have reached
948 * the end of the current mapping.
949 *
950 * If we are in state isl_yaml_sequence_start, then we have just
951 * started a sequence. If the sequence started with a '[',
952 * then we check if the next token is a ']'. If so, then the sequence
953 * is empty and there is no next state at this level.
954 * Otherwise, we assume that there is at least one element in the sequence
955 * (the one from which we derived the indentation in
956 * isl_stream_yaml_read_start_sequence.
957 *
958 * If we are in state isl_yaml_sequence, then there may or may
959 * not be a subsequent element in the same sequence.
960 * In flow format, the next element is preceded by a comma.
961 * In block format, the next element is introduced by a dash with
962 * the same indentation as that of the first element.
963 * If the first token is not a dash or if it has a smaller indentation,
964 * then we have reached the end of the current sequence.
965 */
967{
968 struct isl_token *tok;
969 enum isl_yaml_state state;
970 int indent;
971
972 state = current_state(s);
973 if (state == isl_yaml_none)
975 "not in YAML element", return isl_bool_error);
976 switch (state) {
980 return isl_bool_false;
982 return isl_bool_error;
983 return isl_bool_true;
986 if (!tok) {
987 if (s->eof)
988 isl_stream_error(s, NULL, "unexpected EOF");
989 return isl_bool_error;
990 }
991 if (tok->type == ':') {
992 isl_token_free(tok);
994 return isl_bool_error;
995 return isl_bool_true;
996 }
997 isl_stream_error(s, tok, "expecting ':'");
999 return isl_bool_error;
1002 if (!isl_stream_eat_if_available(s, ','))
1003 return isl_bool_false;
1005 return isl_bool_error;
1006 return isl_bool_true;
1007 }
1008 tok = isl_stream_next_token(s);
1009 if (!tok)
1010 return isl_bool_false;
1011 indent = tok->col - 1;
1013 if (indent < get_yaml_indent(s))
1014 return isl_bool_false;
1016 return isl_bool_error;
1017 return isl_bool_true;
1020 if (isl_stream_next_token_is(s, ']'))
1021 return isl_bool_false;
1023 return isl_bool_error;
1024 return isl_bool_true;
1025 }
1026 tok = isl_stream_next_token(s);
1027 if (!tok) {
1028 if (s->eof)
1029 isl_stream_error(s, NULL, "unexpected EOF");
1030 return isl_bool_error;
1031 }
1032 if (tok->type == '-') {
1033 isl_token_free(tok);
1035 return isl_bool_error;
1036 return isl_bool_true;
1037 }
1038 isl_stream_error(s, tok, "expecting '-'");
1040 return isl_bool_false;
1041 case isl_yaml_sequence:
1044 tok = isl_stream_next_token(s);
1045 if (!tok)
1046 return isl_bool_false;
1047 indent = tok->col - 1;
1048 if (indent < get_yaml_indent(s) || tok->type != '-') {
1050 return isl_bool_false;
1051 }
1052 isl_token_free(tok);
1053 return isl_bool_true;
1054 default:
1056 "unexpected state", return isl_bool_error);
1057 }
1058}
1059
1060/* Start reading a YAML mapping.
1061 * Return isl_stat_ok on success and isl_stat_error on error.
1062 *
1063 * If the first token on the stream is a '{' then we remove this token
1064 * from the stream and keep track of the fact that the mapping
1065 * is given in flow format.
1066 * Otherwise, we assume the first token is the first key of the mapping and
1067 * keep track of its indentation, but keep the token on the stream.
1068 * In both cases, the next token we expect is the first key of the mapping.
1069 */
1071{
1072 struct isl_token *tok;
1073 int indent;
1074
1076 return isl_stat_error;
1077
1078 tok = isl_stream_next_token(s);
1079 if (!tok) {
1080 if (s->eof)
1081 isl_stream_error(s, NULL, "unexpected EOF");
1082 return isl_stat_error;
1083 }
1084 if (isl_token_get_type(tok) == '{') {
1085 isl_token_free(tok);
1087 }
1088 indent = tok->col - 1;
1090
1091 return set_yaml_indent(s, indent);
1092}
1093
1094/* Finish reading a YAML mapping.
1095 * Return isl_stat_ok on success and isl_stat_error on error.
1096 *
1097 * If the mapping started with a '{', then we expect a '}' to close
1098 * the mapping.
1099 * Otherwise, we double-check that the next token (if any)
1100 * has a smaller indentation than that of the current mapping.
1101 */
1103{
1104 struct isl_token *tok;
1105 int indent;
1106
1108 if (isl_stream_eat(s, '}') < 0)
1109 return isl_stat_error;
1110 return pop_state(s);
1111 }
1112
1113 tok = isl_stream_next_token(s);
1114 if (!tok)
1115 return pop_state(s);
1116
1117 indent = tok->col - 1;
1119
1120 if (indent >= get_yaml_indent(s))
1122 "mapping not finished", return isl_stat_error);
1123
1124 return pop_state(s);
1125}
1126
1127/* Start reading a YAML sequence.
1128 * Return isl_stat_ok on success and isl_stat_error on error.
1129 *
1130 * If the first token on the stream is a '[' then we remove this token
1131 * from the stream and keep track of the fact that the sequence
1132 * is given in flow format.
1133 * Otherwise, we assume the first token is the dash that introduces
1134 * the first element of the sequence and keep track of its indentation,
1135 * but keep the token on the stream.
1136 * In both cases, the next token we expect is the first element
1137 * of the sequence.
1138 */
1140{
1141 struct isl_token *tok;
1142 int indent;
1143
1145 return isl_stat_error;
1146
1147 tok = isl_stream_next_token(s);
1148 if (!tok) {
1149 if (s->eof)
1150 isl_stream_error(s, NULL, "unexpected EOF");
1151 return isl_stat_error;
1152 }
1153 if (isl_token_get_type(tok) == '[') {
1154 isl_token_free(tok);
1156 }
1157 indent = tok->col - 1;
1159
1160 return set_yaml_indent(s, indent);
1161}
1162
1163/* Finish reading a YAML sequence.
1164 * Return isl_stat_ok on success and isl_stat_error on error.
1165 *
1166 * If the sequence started with a '[', then we expect a ']' to close
1167 * the sequence.
1168 * Otherwise, we double-check that the next token (if any)
1169 * is not a dash or that it has a smaller indentation than
1170 * that of the current sequence.
1171 */
1173{
1174 struct isl_token *tok;
1175 int indent;
1176 int dash;
1177
1179 if (isl_stream_eat(s, ']') < 0)
1180 return isl_stat_error;
1181 return pop_state(s);
1182 }
1183
1184 tok = isl_stream_next_token(s);
1185 if (!tok)
1186 return pop_state(s);
1187
1188 indent = tok->col - 1;
1189 dash = tok->type == '-';
1191
1192 if (indent >= get_yaml_indent(s) && dash)
1194 "sequence not finished", return isl_stat_error);
1195
1196 return pop_state(s);
1197}
__isl_null isl_pw_aff * isl_pw_aff_free(__isl_take isl_pw_aff *pwaff)
__isl_give isl_printer * isl_printer_print_pw_aff(__isl_take isl_printer *p, __isl_keep isl_pw_aff *pwaff)
Definition: isl_output.c:2886
#define __isl_take
Definition: ctx.h:22
#define isl_calloc_type(ctx, type)
Definition: ctx.h:129
isl_stat
Definition: ctx.h:84
@ isl_stat_error
Definition: ctx.h:85
@ isl_stat_ok
Definition: ctx.h:86
#define __isl_give
Definition: ctx.h:19
#define isl_die(ctx, errno, msg, code)
Definition: ctx.h:137
void isl_ctx_deref(struct isl_ctx *ctx)
Definition: isl_ctx.c:275
#define isl_assert(ctx, test, code)
Definition: ctx.h:152
isl_bool isl_bool_ok(int b)
Definition: isl_ctx.c:46
@ isl_error_invalid
Definition: ctx.h:80
@ isl_error_internal
Definition: ctx.h:79
#define isl_alloc_array(ctx, type, n)
Definition: ctx.h:131
#define __isl_keep
Definition: ctx.h:25
#define isl_alloc_type(ctx, type)
Definition: ctx.h:128
#define isl_realloc_array(ctx, ptr, type, n)
Definition: ctx.h:134
void isl_ctx_ref(struct isl_ctx *ctx)
Definition: isl_ctx.c:270
isl_bool
Definition: ctx.h:89
@ isl_bool_false
Definition: ctx.h:91
@ isl_bool_true
Definition: ctx.h:92
@ isl_bool_error
Definition: ctx.h:90
struct isl_hash_table_entry * isl_hash_table_entry_none
Definition: isl_hash.c:155
uint32_t isl_hash_string(uint32_t hash, const char *s)
Definition: isl_hash.c:15
#define isl_hash_init()
Definition: hash.h:21
void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table)
Definition: isl_hash.c:143
isl_stat isl_hash_table_foreach(isl_ctx *ctx, struct isl_hash_table *table, isl_stat(*fn)(void **entry, void *user), void *user)
Definition: isl_hash.c:215
struct isl_hash_table_entry * isl_hash_table_find(struct isl_ctx *ctx, struct isl_hash_table *table, uint32_t key_hash, isl_bool(*eq)(const void *entry, const void *val), const void *val, int reserve)
Definition: isl_hash.c:157
struct isl_hash_table * isl_hash_table_alloc(struct isl_ctx *ctx, int min_size)
Definition: isl_hash.c:123
__isl_export __isl_give ISL_HMAP __isl_take ISL_KEY __isl_take ISL_VAL * val
Definition: hmap.h:32
isl_stat isl_stat(*) void user)
Definition: hmap.h:39
void isl_ctx_set_full_error(isl_ctx *ctx, enum isl_error error, const char *msg, const char *file, int line)
Definition: isl_ctx.c:119
#define isl_int_is_zero(i)
Definition: isl_int.h:31
#define isl_int_print(out, i, width)
Definition: isl_int.h:40
#define isl_int_read(r, s)
Definition: isl_int_gmp.h:53
#define isl_int_init(i)
Definition: isl_int_gmp.h:11
#define isl_int_clear(i)
Definition: isl_int_gmp.h:12
static isl_stat free_keyword(void **p, void *user)
Definition: isl_stream.c:779
static int isl_stream_getc(__isl_keep isl_stream *s)
Definition: isl_stream.c:279
void isl_stream_error(__isl_keep isl_stream *s, struct isl_token *tok, char *msg)
Definition: isl_stream.c:142
isl_stat isl_stream_yaml_read_start_sequence(__isl_keep isl_stream *s)
Definition: isl_stream.c:1139
void isl_token_free(struct isl_token *tok)
Definition: isl_stream.c:127
__isl_give isl_stream * isl_stream_new_str(struct isl_ctx *ctx, const char *str)
Definition: isl_stream.c:228
int isl_stream_skip_line(__isl_keep isl_stream *s)
Definition: isl_stream.c:376
isl_bool isl_stream_yaml_next(__isl_keep isl_stream *s)
Definition: isl_stream.c:966
static int stream_getc(__isl_keep isl_stream *s)
Definition: isl_stream.c:243
static struct isl_token * next_token(__isl_keep isl_stream *s, int same_line)
Definition: isl_stream.c:387
static void isl_stream_ungetc(__isl_keep isl_stream *s, int c)
Definition: isl_stream.c:268
static int isl_stream_push_char(__isl_keep isl_stream *s, int c)
Definition: isl_stream.c:297
static isl_stat set_yaml_indent(__isl_keep isl_stream *s, int indent)
Definition: isl_stream.c:904
char * isl_stream_read_ident_if_available(__isl_keep isl_stream *s)
Definition: isl_stream.c:731
void isl_stream_push_token(__isl_keep isl_stream *s, struct isl_token *tok)
Definition: isl_stream.c:311
static enum isl_token_type check_keywords(__isl_keep isl_stream *s)
Definition: isl_stream.c:317
int isl_stream_is_empty(__isl_keep isl_stream *s)
Definition: isl_stream.c:766
enum isl_token_type isl_stream_register_keyword(__isl_keep isl_stream *s, const char *name)
Definition: isl_stream.c:31
static int update_state(__isl_keep isl_stream *s, enum isl_yaml_state state)
Definition: isl_stream.c:875
void isl_stream_flush_tokens(__isl_keep isl_stream *s)
Definition: isl_stream.c:789
__isl_give isl_stream * isl_stream_new_file(struct isl_ctx *ctx, FILE *file)
Definition: isl_stream.c:219
isl_ctx * isl_stream_get_ctx(__isl_keep isl_stream *s)
Definition: isl_stream.c:800
isl_stat isl_stream_yaml_read_start_mapping(__isl_keep isl_stream *s)
Definition: isl_stream.c:1070
int isl_stream_eat(__isl_keep isl_stream *s, int type)
Definition: isl_stream.c:747
struct isl_token * isl_stream_next_token(__isl_keep isl_stream *s)
Definition: isl_stream.c:693
isl_stat isl_stream_yaml_read_end_mapping(__isl_keep isl_stream *s)
Definition: isl_stream.c:1102
struct isl_token * isl_stream_next_token_on_same_line(__isl_keep isl_stream *s)
Definition: isl_stream.c:698
static enum isl_yaml_state current_state(__isl_keep isl_stream *s)
Definition: isl_stream.c:891
static isl_stat pop_state(__isl_keep isl_stream *s)
Definition: isl_stream.c:859
int isl_stream_next_token_is(__isl_keep isl_stream *s, int type)
Definition: isl_stream.c:718
__isl_give char * isl_token_get_str(isl_ctx *ctx, struct isl_token *tok)
Definition: isl_stream.c:115
void isl_stream_free(__isl_take isl_stream *s)
Definition: isl_stream.c:805
static int get_yaml_indent(__isl_keep isl_stream *s)
Definition: isl_stream.c:918
isl_stat isl_stream_yaml_read_end_sequence(__isl_keep isl_stream *s)
Definition: isl_stream.c:1172
__isl_give isl_val * isl_token_get_val(isl_ctx *ctx, struct isl_token *tok)
Definition: isl_stream.c:93
isl_bool isl_token_has_str(struct isl_token *tok)
Definition: isl_stream.c:106
static __isl_give isl_stream * isl_stream_new(struct isl_ctx *ctx)
Definition: isl_stream.c:188
struct isl_token * isl_token_new(isl_ctx *ctx, int line, int col, unsigned on_new_line)
Definition: isl_stream.c:70
int isl_token_get_type(struct isl_token *tok)
Definition: isl_stream.c:86
static isl_bool same_name(const void *entry, const void *val)
Definition: isl_stream.c:24
static int push_state(__isl_keep isl_stream *s, enum isl_yaml_state state)
Definition: isl_stream.c:829
int isl_stream_eat_if_available(__isl_keep isl_stream *s, int type)
Definition: isl_stream.c:703
enum isl_fold type
Definition: isl_test.c:4017
const char * p
Definition: isl_test.c:8643
const char * name
Definition: isl_test.c:10938
const char * str
Definition: isl_test.c:2095
__isl_give isl_val * isl_val_int_from_isl_int(isl_ctx *ctx, isl_int n)
Definition: isl_val.c:185
#define ISL_YAML_INDENT_FLOW
Definition: isl_yaml.h:4
isl_yaml_state
Definition: isl_yaml.h:6
@ isl_yaml_sequence
Definition: isl_yaml.h:15
@ isl_yaml_mapping_val
Definition: isl_yaml.h:12
@ isl_yaml_sequence_start
Definition: isl_yaml.h:14
@ isl_yaml_mapping_key_start
Definition: isl_yaml.h:9
@ isl_yaml_none
Definition: isl_yaml.h:7
@ isl_yaml_mapping_key
Definition: isl_yaml.h:10
__isl_give isl_printer * isl_printer_print_map(__isl_take isl_printer *printer, __isl_keep isl_map *map)
Definition: isl_output.c:1593
__isl_null isl_map * isl_map_free(__isl_take isl_map *map)
Definition: isl_map.c:6421
#define ISL_ON_ERROR_ABORT
Definition: options.h:31
#define ISL_ON_ERROR_CONTINUE
Definition: options.h:30
__isl_null isl_printer * isl_printer_free(__isl_take isl_printer *printer)
Definition: isl_printer.c:269
__isl_give isl_printer * isl_printer_to_file(isl_ctx *ctx, FILE *file)
Definition: isl_printer.c:217
isl_token_type
Definition: stream.h:24
@ ISL_TOKEN_ERROR
Definition: stream.h:24
@ ISL_TOKEN_AND
Definition: stream.h:31
@ ISL_TOKEN_FLOOR
Definition: stream.h:39
@ ISL_TOKEN_EXISTS
Definition: stream.h:32
@ ISL_TOKEN_LE
Definition: stream.h:27
@ ISL_TOKEN_TRUE
Definition: stream.h:35
@ ISL_TOKEN_LT
Definition: stream.h:27
@ ISL_TOKEN_DEF
Definition: stream.h:33
@ ISL_TOKEN_INFTY
Definition: stream.h:33
@ ISL_TOKEN_STRING
Definition: stream.h:37
@ ISL_TOKEN_LEX_GE
Definition: stream.h:29
@ ISL_TOKEN_MOD
Definition: stream.h:36
@ ISL_TOKEN_NOT
Definition: stream.h:32
@ ISL_TOKEN_NE
Definition: stream.h:28
@ ISL_TOKEN_VALUE
Definition: stream.h:25
@ ISL_TOKEN_CEIL
Definition: stream.h:39
@ ISL_TOKEN_LEX_LE
Definition: stream.h:29
@ ISL_TOKEN_FLOORD
Definition: stream.h:36
@ ISL_TOKEN_CEILD
Definition: stream.h:36
@ ISL_TOKEN_MAP
Definition: stream.h:38
@ ISL_TOKEN_GE
Definition: stream.h:26
@ ISL_TOKEN_RAT
Definition: stream.h:34
@ ISL_TOKEN_INT_DIV
Definition: stream.h:41
@ ISL_TOKEN_LEX_GT
Definition: stream.h:30
@ ISL_TOKEN_TO
Definition: stream.h:31
@ ISL_TOKEN_GT
Definition: stream.h:27
@ ISL_TOKEN_UNKNOWN
Definition: stream.h:25
@ ISL_TOKEN_LAST
Definition: stream.h:42
@ ISL_TOKEN_OR
Definition: stream.h:32
@ ISL_TOKEN_NAN
Definition: stream.h:33
@ ISL_TOKEN_LEX_LT
Definition: stream.h:30
@ ISL_TOKEN_IDENT
Definition: stream.h:26
@ ISL_TOKEN_FALSE
Definition: stream.h:35
@ ISL_TOKEN_IMPLIES
Definition: stream.h:40
@ ISL_TOKEN_EQ_EQ
Definition: stream.h:28
@ ISL_TOKEN_AFF
Definition: stream.h:38
@ ISL_TOKEN_MAX
Definition: stream.h:34
@ ISL_TOKEN_MIN
Definition: stream.h:34
Definition: hash.h:45
void * data
Definition: hash.h:47
enum isl_token_type type
Definition: isl_stream.c:21
char * name
Definition: isl_stream.c:20
unsigned int on_new_line
isl_pw_aff * pwaff
union isl_token::@24 u
isl_map * map
unsigned is_keyword