1 #include <barvinok/util.h>
2 #include "evalue_read.h"
4 #define ALLOC(type) (type*)malloc(sizeof(type))
5 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
7 enum token_type
{ TOKEN_UNKNOWN
= 256, TOKEN_VALUE
, TOKEN_IDENT
, TOKEN_GE
,
8 TOKEN_NE
, TOKEN_UNION
, TOKEN_VARS
};
22 static struct token
*token_new(int line
, int col
)
24 struct token
*tok
= ALLOC(struct token
);
30 void token_free(struct token
*tok
)
32 if (tok
->type
== TOKEN_VALUE
)
33 value_clear(tok
->u
.v
);
34 else if (tok
->type
== TOKEN_IDENT
)
50 struct token
*tokens
[5];
54 static struct stream
* stream_new(FILE *file
)
57 struct stream
*s
= ALLOC(struct stream
);
60 s
->buffer
= (char*)malloc(s
->size
);
66 for (i
= 0; i
< 5; ++i
)
72 static void stream_free(struct stream
*s
)
75 assert(s
->n_token
== 0);
79 static int stream_getc(struct stream
*s
)
98 static void stream_ungetc(struct stream
*s
, int c
)
104 static void stream_push_char(struct stream
*s
, int c
)
106 if (s
->len
>= s
->size
) {
107 s
->size
= (3*s
->size
)/2;
108 s
->buffer
= (char*)realloc(s
->buffer
, s
->size
);
110 s
->buffer
[s
->len
++] = c
;
113 static struct token
*stream_push_token(struct stream
*s
, struct token
*tok
)
115 assert(s
->n_token
< 5);
116 s
->tokens
[s
->n_token
++] = tok
;
119 static struct token
*stream_next_token(struct stream
*s
)
126 return s
->tokens
[--s
->n_token
];
131 while ((c
= stream_getc(s
)) != -1 && isspace(c
))
153 tok
= token_new(line
, col
);
154 tok
->type
= (enum token_type
)c
;
157 if (c
== '-' || isdigit(c
)) {
158 tok
= token_new(line
, col
);
159 tok
->type
= TOKEN_VALUE
;
160 value_init(tok
->u
.v
);
161 stream_push_char(s
, c
);
162 while ((c
= stream_getc(s
)) != -1 && isdigit(c
))
163 stream_push_char(s
, c
);
166 if (s
->len
== 1 && s
->buffer
[0] == '-')
167 value_set_si(tok
->u
.v
, -1);
169 stream_push_char(s
, '\0');
170 mpz_set_str(tok
->u
.v
, s
->buffer
, 0);
174 if (c
== '#' || isalpha(c
)) {
175 tok
= token_new(line
, col
);
176 stream_push_char(s
, c
);
177 while ((c
= stream_getc(s
)) != -1 && isalnum(c
))
178 stream_push_char(s
, c
);
181 stream_push_char(s
, '\0');
182 if (!strcmp(s
->buffer
, "#variables")) {
183 tok
->type
= TOKEN_VARS
;
184 } else if (s
->buffer
[0] == '#') {
185 tok
->type
= TOKEN_UNKNOWN
;
186 } else if (!strcmp(s
->buffer
, "UNION")) {
187 tok
->type
= TOKEN_UNION
;
189 tok
->type
= TOKEN_IDENT
;
190 tok
->u
.s
= strdup(s
->buffer
);
195 if ((c
= stream_getc(s
)) == '=') {
196 tok
= token_new(line
, col
);
197 tok
->type
= TOKEN_GE
;
204 if ((c
= stream_getc(s
)) == '=') {
205 tok
= token_new(line
, col
);
206 tok
->type
= TOKEN_NE
;
213 tok
= token_new(line
, col
);
214 tok
->type
= TOKEN_UNKNOWN
;
218 void stream_error(struct stream
*s
, struct token
*tok
, char *msg
)
220 int line
= tok
? tok
->line
: s
->line
;
221 int col
= tok
? tok
->col
: s
->col
;
222 fprintf(stderr
, "syntax error (%d, %d): %s\n", line
, col
, msg
);
225 fprintf(stderr
, "got '%c'\n", tok
->type
);
232 struct parameter
*next
;
235 struct parameter
*parameter_new(char *name
, int pos
, struct parameter
*next
)
237 struct parameter
*p
= ALLOC(struct parameter
);
238 p
->name
= strdup(name
);
244 static int parameter_pos(struct parameter
**p
, const char *s
, int len
)
246 int pos
= *p
? (*p
)->pos
+1 : 0;
251 for (q
= *p
; q
; q
= q
->next
) {
252 if (strncmp(q
->name
, s
, len
) == 0)
258 *p
= parameter_new(s
, pos
, *p
);
262 static int optional_power(struct stream
*s
)
266 tok
= stream_next_token(s
);
269 if (tok
->type
!= '^') {
270 stream_push_token(s
, tok
);
274 tok
= stream_next_token(s
);
275 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
276 stream_error(s
, tok
, "expecting exponent");
278 stream_push_token(s
, tok
);
281 pow
= VALUE_TO_INT(tok
->u
.v
);
286 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
);
287 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
);
289 static evalue
*create_fract_like(struct stream
*s
, evalue
*arg
, enode_type type
,
290 struct parameter
**p
)
294 pow
= optional_power(s
);
298 e
->x
.p
= new_enode(type
, pow
+2, -1);
299 value_clear(e
->x
.p
->arr
[0].d
);
300 e
->x
.p
->arr
[0] = *arg
;
302 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 1, 1);
304 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 0, 1);
309 static evalue
*create_relation(evalue
*arg
, int ne
)
315 e
->x
.p
= new_enode(relation
, 2+ne
, 0);
316 value_clear(e
->x
.p
->arr
[0].d
);
317 e
->x
.p
->arr
[0] = *arg
;
320 evalue_set_si(&e
->x
.p
->arr
[1], 0, 1);
321 evalue_set_si(&e
->x
.p
->arr
[1+ne
], 1, 1);
326 static evalue
*read_fract(struct stream
*s
, struct token
*tok
, struct parameter
**p
)
330 tok
= stream_next_token(s
);
332 assert(tok
->type
== '{');
335 arg
= evalue_read_term(s
, p
);
336 tok
= stream_next_token(s
);
337 if (!tok
|| tok
->type
!= '}') {
338 stream_error(s
, tok
, "expecting \"}\"");
340 stream_push_token(s
, tok
);
344 return create_fract_like(s
, arg
, fractional
, p
);
347 static evalue
*read_periodic(struct stream
*s
, struct parameter
**p
)
355 tok
= stream_next_token(s
);
356 assert(tok
&& tok
->type
== '[');
360 list
= (evalue
**)malloc(len
* sizeof(evalue
*));
364 evalue
*e
= evalue_read_term(s
, p
);
366 stream_error(s
, NULL
, "missing argument or list element");
371 list
= (evalue
**)realloc(list
, len
* sizeof(evalue
*));
375 tok
= stream_next_token(s
);
377 stream_error(s
, NULL
, "unexpected EOF");
380 if (tok
->type
!= ',')
385 if (n
== 1 && (tok
->type
== '=' || tok
->type
== TOKEN_NE
)) {
386 int ne
= tok
->type
== TOKEN_NE
;
388 tok
= stream_next_token(s
);
389 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
390 stream_error(s
, tok
, "expecting \"0\"");
392 stream_push_token(s
, tok
);
396 tok
= stream_next_token(s
);
397 if (!tok
|| tok
->type
!= ']') {
398 stream_error(s
, tok
, "expecting \"]\"");
400 stream_push_token(s
, tok
);
404 e
= create_relation(list
[0], ne
);
409 if (tok
->type
!= ']') {
410 stream_error(s
, tok
, "expecting \"]\"");
411 stream_push_token(s
, tok
);
417 tok
= stream_next_token(s
);
418 if (tok
->type
== '_') {
421 tok
= stream_next_token(s
);
422 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
423 stream_error(s
, tok
, "expecting identifier");
425 stream_push_token(s
, tok
);
430 pos
= parameter_pos(p
, tok
->u
.s
, -1);
432 e
->x
.p
= new_enode(periodic
, n
, pos
+1);
434 value_clear(e
->x
.p
->arr
[n
].d
);
435 e
->x
.p
->arr
[n
] = *list
[n
];
439 stream_push_token(s
, tok
);
440 e
= create_fract_like(s
, list
[0], flooring
, p
);
443 stream_error(s
, tok
, "unexpected token");
444 stream_push_token(s
, tok
);
449 free_evalue_refs(list
[n
]);
456 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
)
461 tok
= stream_next_token(s
);
465 if (tok
->type
== '(') {
467 e
= evalue_read_term(s
, p
);
468 tok
= stream_next_token(s
);
469 if (!tok
|| tok
->type
!= ')') {
470 stream_error(s
, tok
, "expecting \")\"");
472 stream_push_token(s
, tok
);
475 } else if (tok
->type
== TOKEN_VALUE
) {
478 value_set_si(e
->d
, 1);
480 value_assign(e
->x
.n
, tok
->u
.v
);
482 tok
= stream_next_token(s
);
483 if (tok
&& tok
->type
== '/') {
485 tok
= stream_next_token(s
);
486 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
487 stream_error(s
, tok
, "expecting denominator");
489 stream_push_token(s
, tok
);
492 value_assign(e
->d
, tok
->u
.v
);
495 stream_push_token(s
, tok
);
496 } else if (tok
->type
== TOKEN_IDENT
) {
497 int pos
= parameter_pos(p
, tok
->u
.s
, -1);
498 int pow
= optional_power(s
);
502 e
->x
.p
= new_enode(polynomial
, pow
+1, pos
+1);
503 evalue_set_si(&e
->x
.p
->arr
[pow
], 1, 1);
505 evalue_set_si(&e
->x
.p
->arr
[pow
], 0, 1);
506 } else if (tok
->type
== '[') {
507 stream_push_token(s
, tok
);
508 e
= read_periodic(s
, p
);
509 } else if (tok
->type
== '{') {
510 stream_push_token(s
, tok
);
511 e
= read_fract(s
, tok
, p
);
514 tok
= stream_next_token(s
);
515 if (tok
&& tok
->type
== '*') {
518 e2
= evalue_read_factor(s
, p
);
520 stream_error(s
, NULL
, "unexpected EOF");
524 free_evalue_refs(e2
);
527 stream_push_token(s
, tok
);
532 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
)
537 e
= evalue_read_factor(s
, p
);
541 tok
= stream_next_token(s
);
545 if (tok
->type
== '+') {
548 e2
= evalue_read_term(s
, p
);
550 stream_error(s
, NULL
, "unexpected EOF");
554 free_evalue_refs(e2
);
557 stream_push_token(s
, tok
);
565 struct constraint
*next
;
566 struct constraint
*union_next
;
569 static struct constraint
*constraint_new()
571 struct constraint
*c
= ALLOC(struct constraint
);
573 c
->v
= Vector_Alloc(16);
575 c
->union_next
= NULL
;
579 static void constraint_free(struct constraint
*c
)
582 struct constraint
*next
= c
->next
? c
->next
: c
->union_next
;
589 static void constraint_extend(struct constraint
*c
, int pos
)
592 if (pos
< c
->v
->Size
)
595 v
= Vector_Alloc((3*c
->v
->Size
)/2);
596 Vector_Copy(c
->v
->p
, v
->p
, c
->v
->Size
);
601 static int evalue_read_constraint(struct stream
*s
, struct parameter
**p
,
602 struct constraint
**constraints
,
603 struct constraint
*union_next
)
606 struct constraint
*c
= NULL
;
608 while ((tok
= stream_next_token(s
))) {
611 if (tok
->type
== '+')
613 else if (tok
->type
== TOKEN_IDENT
) {
615 c
= constraint_new();
616 pos
= parameter_pos(p
, tok
->u
.s
, -1);
617 constraint_extend(c
, 1+pos
);
618 value_set_si(c
->v
->p
[1+pos
], 1);
620 } else if (tok
->type
== TOKEN_VALUE
) {
622 c
= constraint_new();
623 tok2
= stream_next_token(s
);
624 if (tok2
&& tok2
->type
== TOKEN_IDENT
) {
625 pos
= parameter_pos(p
, tok2
->u
.s
, -1);
626 constraint_extend(c
, 1+pos
);
627 value_assign(c
->v
->p
[1+pos
], tok
->u
.v
);
632 stream_push_token(s
, tok2
);
633 value_assign(c
->v
->p
[0], tok
->u
.v
);
636 } else if (tok
->type
== TOKEN_GE
|| tok
->type
== '=') {
637 int type
= tok
->type
== TOKEN_GE
;
639 tok
= stream_next_token(s
);
640 if (!tok
|| tok
->type
!= TOKEN_VALUE
|| value_notzero_p(tok
->u
.v
)) {
641 stream_error(s
, tok
, "expecting \"0\"");
643 stream_push_token(s
, tok
);
647 c
->next
= *constraints
;
648 c
->union_next
= union_next
;
655 stream_push_token(s
, tok
);
657 stream_error(s
, tok
, "unexpected token");
666 static struct constraint
*evalue_read_domain(struct stream
*s
, struct parameter
**p
,
669 struct constraint
*constraints
= NULL
;
670 struct constraint
*union_next
= NULL
;
674 tok
= stream_next_token(s
);
677 stream_push_token(s
, tok
);
680 while (evalue_read_constraint(s
, p
, &constraints
, union_next
)) {
681 tok
= stream_next_token(s
);
683 if (tok
->type
== TOKEN_UNION
) {
685 tok
= stream_next_token(s
);
687 stream_error(s
, NULL
, "unexpected EOF");
690 stream_push_token(s
, tok
);
691 union_next
= constraints
;
695 stream_push_token(s
, tok
);
696 /* empty line separates domain from evalue */
697 if (tok
->line
> line
+1)
707 struct constraint
*constraints
;
709 struct section
*next
;
712 static char **extract_parameters(struct parameter
*p
, unsigned *nparam
)
717 *nparam
= p
? p
->pos
+1 : 0;
718 params
= ALLOCN(char *, *nparam
);
719 for (i
= 0; i
< *nparam
; ++i
) {
720 struct parameter
*next
= p
->next
;
721 params
[p
->pos
] = p
->name
;
728 static Polyhedron
*constraints2domain(struct constraint
*constraints
,
729 unsigned nparam
, unsigned MaxRays
)
734 struct constraint
*c
;
735 struct constraint
*union_next
= NULL
;
737 for (n
= 0, c
= constraints
; c
; ++n
, c
= c
->next
)
739 M
= Matrix_Alloc(n
, 1+nparam
+1);
741 struct constraint
*next
= constraints
->next
;
742 union_next
= constraints
->union_next
;
743 Vector_Copy(constraints
->v
->p
+1, M
->p
[n
]+1, nparam
);
744 if (constraints
->type
)
745 value_set_si(M
->p
[n
][0], 1);
746 value_assign(M
->p
[n
][1+nparam
], constraints
->v
->p
[0]);
747 constraints
->next
= NULL
;
748 constraints
->union_next
= NULL
;
749 constraint_free(constraints
);
752 D
= Constraints2Polyhedron(M
, MaxRays
);
756 D
= DomainConcat(D
, constraints2domain(union_next
, nparam
, MaxRays
));
760 static evalue
*evalue_read_partition(struct stream
*s
, struct parameter
*p
,
762 unsigned *nparam
, unsigned MaxRays
)
764 struct section
*part
= NULL
;
765 struct constraint
*constraints
;
769 while ((constraints
= evalue_read_domain(s
, &p
, MaxRays
))) {
770 evalue
*e
= evalue_read_term(s
, &p
);
772 stream_error(s
, NULL
, "missing evalue");
775 struct section
*sect
= ALLOC(struct section
);
776 sect
->constraints
= constraints
;
787 *ppp
= extract_parameters(p
, nparam
);
790 e
->x
.p
= new_enode(partition
, 2*m
, *nparam
);
792 for (j
= 0; j
< m
; ++j
) {
794 struct section
*next
= part
->next
;
795 constraints
= part
->constraints
;
796 D
= constraints2domain(part
->constraints
, *nparam
, MaxRays
);
797 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[2*j
], D
);
798 value_clear(e
->x
.p
->arr
[2*j
+1].d
);
799 e
->x
.p
->arr
[2*j
+1] = *part
->e
;
808 static evalue
*evalue_read(struct stream
*s
, const char *var_list
, char ***ppp
,
809 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
813 struct parameter
*p
= NULL
;
818 while ((next
= strchr(var_list
, ','))) {
820 parameter_pos(&p
, var_list
, next
-var_list
);
823 if (strlen(var_list
) > 0)
824 parameter_pos(&p
, var_list
, -1);
825 nv
= p
? p
->pos
+1 : 0;
829 if (!(tok
= stream_next_token(s
)))
832 if (tok
->type
== TOKEN_VARS
) {
835 tok
= stream_next_token(s
);
836 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
837 stream_error(s
, tok
, "expecting identifier");
841 parameter_pos(&p
, tok
->u
.s
, -1);
843 tok
= stream_next_token(s
);
844 if (!tok
|| tok
->type
!= ',')
851 nv
= p
? p
->pos
+1 : 0;
854 if (tok
->type
== '(') {
855 stream_push_token(s
, tok
);
856 e
= evalue_read_term(s
, &p
);
857 *ppp
= extract_parameters(p
, nparam
);
858 } else if (tok
->type
== TOKEN_VALUE
) {
859 struct token
*tok2
= stream_next_token(s
);
861 stream_push_token(s
, tok2
);
862 stream_push_token(s
, tok
);
863 if (tok2
&& (tok2
->type
== TOKEN_IDENT
|| tok2
->type
== TOKEN_GE
))
864 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
866 e
= evalue_read_term(s
, &p
);
867 *ppp
= extract_parameters(p
, nparam
);
869 } else if (tok
->type
== TOKEN_IDENT
) {
870 stream_push_token(s
, tok
);
871 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
873 stream_error(s
, tok
, "unexpected token");
874 *nparam
= nv
== -1 ? 0 : nv
;
885 evalue
*evalue_read_from_file(FILE *in
, const char *var_list
, char ***ppp
,
886 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
889 struct stream
*s
= stream_new(in
);
890 e
= evalue_read(s
, var_list
, ppp
, nvar
, nparam
, MaxRays
);