2 #include <barvinok/util.h>
3 #include "evalue_read.h"
5 #define ALLOC(type) (type*)malloc(sizeof(type))
6 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
8 enum token_type
{ TOKEN_UNKNOWN
= 256, TOKEN_VALUE
, TOKEN_IDENT
, TOKEN_GE
,
9 TOKEN_NE
, TOKEN_UNION
, TOKEN_VARS
};
23 static struct token
*token_new(int line
, int col
)
25 struct token
*tok
= ALLOC(struct token
);
31 void token_free(struct token
*tok
)
33 if (tok
->type
== TOKEN_VALUE
)
34 value_clear(tok
->u
.v
);
35 else if (tok
->type
== TOKEN_IDENT
)
52 struct token
*tokens
[5];
56 static struct stream
* stream_new()
59 struct stream
*s
= ALLOC(struct stream
);
63 s
->buffer
= (char*)malloc(s
->size
);
69 for (i
= 0; i
< 5; ++i
)
75 static struct stream
* stream_new_file(FILE *file
)
77 struct stream
*s
= stream_new();
82 static struct stream
* stream_new_str(const char *str
)
84 struct stream
*s
= stream_new();
89 static int stream_getc(struct stream
*s
)
114 static void stream_ungetc(struct stream
*s
, int c
)
123 static void stream_push_char(struct stream
*s
, int c
)
125 if (s
->len
>= s
->size
) {
126 s
->size
= (3*s
->size
)/2;
127 s
->buffer
= (char*)realloc(s
->buffer
, s
->size
);
129 s
->buffer
[s
->len
++] = c
;
132 static struct token
*stream_push_token(struct stream
*s
, struct token
*tok
)
134 assert(s
->n_token
< 5);
135 s
->tokens
[s
->n_token
++] = tok
;
138 static struct token
*stream_next_token(struct stream
*s
)
145 return s
->tokens
[--s
->n_token
];
150 while ((c
= stream_getc(s
)) != -1 && isspace(c
))
172 tok
= token_new(line
, col
);
173 tok
->type
= (enum token_type
)c
;
176 if (c
== '-' || isdigit(c
)) {
177 tok
= token_new(line
, col
);
178 tok
->type
= TOKEN_VALUE
;
179 value_init(tok
->u
.v
);
180 stream_push_char(s
, c
);
181 while ((c
= stream_getc(s
)) != -1 && isdigit(c
))
182 stream_push_char(s
, c
);
185 if (s
->len
== 1 && s
->buffer
[0] == '-')
186 value_set_si(tok
->u
.v
, -1);
188 stream_push_char(s
, '\0');
189 mpz_set_str(tok
->u
.v
, s
->buffer
, 0);
193 if (c
== '#' || isalpha(c
)) {
194 tok
= token_new(line
, col
);
195 stream_push_char(s
, c
);
196 while ((c
= stream_getc(s
)) != -1 && isalnum(c
))
197 stream_push_char(s
, c
);
200 stream_push_char(s
, '\0');
201 if (!strcmp(s
->buffer
, "#variables")) {
202 tok
->type
= TOKEN_VARS
;
203 } else if (s
->buffer
[0] == '#') {
204 tok
->type
= TOKEN_UNKNOWN
;
205 } else if (!strcmp(s
->buffer
, "UNION")) {
206 tok
->type
= TOKEN_UNION
;
208 tok
->type
= TOKEN_IDENT
;
209 tok
->u
.s
= strdup(s
->buffer
);
214 if ((c
= stream_getc(s
)) == '=') {
215 tok
= token_new(line
, col
);
216 tok
->type
= TOKEN_GE
;
223 if ((c
= stream_getc(s
)) == '=') {
224 tok
= token_new(line
, col
);
225 tok
->type
= TOKEN_NE
;
232 tok
= token_new(line
, col
);
233 tok
->type
= TOKEN_UNKNOWN
;
237 void stream_error(struct stream
*s
, struct token
*tok
, char *msg
)
239 int line
= tok
? tok
->line
: s
->line
;
240 int col
= tok
? tok
->col
: s
->col
;
241 fprintf(stderr
, "syntax error (%d, %d): %s\n", line
, col
, msg
);
244 fprintf(stderr
, "got '%c'\n", tok
->type
);
246 fprintf(stderr
, "got token type %d\n", tok
->type
);
250 static void stream_free(struct stream
*s
)
253 if (s
->n_token
!= 0) {
254 struct token
*tok
= stream_next_token(s
);
255 stream_error(s
, tok
, "unexpected token");
263 struct parameter
*next
;
266 struct parameter
*parameter_new(const char *name
, int len
,
267 int pos
, struct parameter
*next
)
269 struct parameter
*p
= ALLOC(struct parameter
);
270 p
->name
= strdup(name
);
277 static int parameter_pos(struct parameter
**p
, const char *s
, int len
)
279 int pos
= *p
? (*p
)->pos
+1 : 0;
284 for (q
= *p
; q
; q
= q
->next
) {
285 if (strncmp(q
->name
, s
, len
) == 0 && q
->name
[len
] == '\0')
291 *p
= parameter_new(s
, len
, pos
, *p
);
295 static int optional_power(struct stream
*s
)
299 tok
= stream_next_token(s
);
302 if (tok
->type
!= '^') {
303 stream_push_token(s
, tok
);
307 tok
= stream_next_token(s
);
308 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
309 stream_error(s
, tok
, "expecting exponent");
311 stream_push_token(s
, tok
);
314 pow
= VALUE_TO_INT(tok
->u
.v
);
319 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
);
320 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
);
322 static evalue
*create_fract_like(struct stream
*s
, evalue
*arg
, enode_type type
,
323 struct parameter
**p
)
327 pow
= optional_power(s
);
331 e
->x
.p
= new_enode(type
, pow
+2, -1);
332 value_clear(e
->x
.p
->arr
[0].d
);
333 e
->x
.p
->arr
[0] = *arg
;
335 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 1, 1);
337 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 0, 1);
342 static evalue
*create_relation(evalue
*arg
, int ne
)
348 e
->x
.p
= new_enode(relation
, 2+ne
, 0);
349 value_clear(e
->x
.p
->arr
[0].d
);
350 e
->x
.p
->arr
[0] = *arg
;
353 evalue_set_si(&e
->x
.p
->arr
[1], 0, 1);
354 evalue_set_si(&e
->x
.p
->arr
[1+ne
], 1, 1);
359 static evalue
*read_fract(struct stream
*s
, struct token
*tok
, struct parameter
**p
)
363 tok
= stream_next_token(s
);
365 assert(tok
->type
== '{');
368 arg
= evalue_read_term(s
, p
);
369 tok
= stream_next_token(s
);
370 if (!tok
|| tok
->type
!= '}') {
371 stream_error(s
, tok
, "expecting \"}\"");
373 stream_push_token(s
, tok
);
377 return create_fract_like(s
, arg
, fractional
, p
);
380 static evalue
*read_periodic(struct stream
*s
, struct parameter
**p
)
388 tok
= stream_next_token(s
);
389 assert(tok
&& tok
->type
== '[');
393 list
= (evalue
**)malloc(len
* sizeof(evalue
*));
397 evalue
*e
= evalue_read_term(s
, p
);
399 stream_error(s
, NULL
, "missing argument or list element");
404 list
= (evalue
**)realloc(list
, len
* sizeof(evalue
*));
408 tok
= stream_next_token(s
);
410 stream_error(s
, NULL
, "unexpected EOF");
413 if (tok
->type
!= ',')
418 if (n
== 1 && (tok
->type
== '=' || tok
->type
== TOKEN_NE
)) {
419 int ne
= tok
->type
== TOKEN_NE
;
421 tok
= stream_next_token(s
);
422 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
423 stream_error(s
, tok
, "expecting \"0\"");
425 stream_push_token(s
, tok
);
429 tok
= stream_next_token(s
);
430 if (!tok
|| tok
->type
!= ']') {
431 stream_error(s
, tok
, "expecting \"]\"");
433 stream_push_token(s
, tok
);
437 e
= create_relation(list
[0], ne
);
442 if (tok
->type
!= ']') {
443 stream_error(s
, tok
, "expecting \"]\"");
444 stream_push_token(s
, tok
);
450 tok
= stream_next_token(s
);
451 if (tok
&& tok
->type
== '_') {
454 tok
= stream_next_token(s
);
455 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
456 stream_error(s
, tok
, "expecting identifier");
458 stream_push_token(s
, tok
);
463 pos
= parameter_pos(p
, tok
->u
.s
, -1);
465 e
->x
.p
= new_enode(periodic
, n
, pos
+1);
467 value_clear(e
->x
.p
->arr
[n
].d
);
468 e
->x
.p
->arr
[n
] = *list
[n
];
473 stream_push_token(s
, tok
);
474 e
= create_fract_like(s
, list
[0], flooring
, p
);
477 stream_error(s
, tok
, "unexpected token");
479 stream_push_token(s
, tok
);
484 evalue_free(list
[n
]);
489 /* frees product on error */
490 static evalue
*read_factor_and_multiply(struct stream
*s
, struct parameter
**p
,
494 e2
= evalue_read_factor(s
, p
);
496 stream_error(s
, NULL
, "unexpected EOF");
497 evalue_free(product
);
505 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
)
510 tok
= stream_next_token(s
);
514 if (tok
->type
== '(') {
516 e
= evalue_read_term(s
, p
);
517 tok
= stream_next_token(s
);
518 if (!tok
|| tok
->type
!= ')') {
519 stream_error(s
, tok
, "expecting \")\"");
521 stream_push_token(s
, tok
);
524 } else if (tok
->type
== TOKEN_VALUE
) {
527 value_set_si(e
->d
, 1);
529 value_assign(e
->x
.n
, tok
->u
.v
);
531 tok
= stream_next_token(s
);
532 if (tok
&& tok
->type
== '/') {
534 tok
= stream_next_token(s
);
535 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
536 stream_error(s
, tok
, "expecting denominator");
538 stream_push_token(s
, tok
);
541 value_assign(e
->d
, tok
->u
.v
);
543 } else if (tok
&& tok
->type
== TOKEN_IDENT
) {
544 stream_push_token(s
, tok
);
545 e
= read_factor_and_multiply(s
, p
, e
);
547 stream_push_token(s
, tok
);
548 } else if (tok
->type
== TOKEN_IDENT
) {
549 int pos
= parameter_pos(p
, tok
->u
.s
, -1);
550 int pow
= optional_power(s
);
554 e
->x
.p
= new_enode(polynomial
, pow
+1, pos
+1);
555 evalue_set_si(&e
->x
.p
->arr
[pow
], 1, 1);
557 evalue_set_si(&e
->x
.p
->arr
[pow
], 0, 1);
558 } else if (tok
->type
== '[') {
559 stream_push_token(s
, tok
);
560 e
= read_periodic(s
, p
);
561 } else if (tok
->type
== '{') {
562 stream_push_token(s
, tok
);
563 e
= read_fract(s
, tok
, p
);
566 tok
= stream_next_token(s
);
567 if (tok
&& tok
->type
== '*') {
569 e
= read_factor_and_multiply(s
, p
, e
);
571 stream_push_token(s
, tok
);
576 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
)
581 e
= evalue_read_factor(s
, p
);
585 tok
= stream_next_token(s
);
589 if (tok
->type
== '+' || tok
->type
== TOKEN_VALUE
) {
591 if (tok
->type
== '+')
594 stream_push_token(s
, tok
);
595 e2
= evalue_read_term(s
, p
);
597 stream_error(s
, NULL
, "unexpected EOF");
603 stream_push_token(s
, tok
);
611 struct constraint
*next
;
612 struct constraint
*union_next
;
615 static struct constraint
*constraint_new()
617 struct constraint
*c
= ALLOC(struct constraint
);
619 c
->v
= Vector_Alloc(16);
621 c
->union_next
= NULL
;
625 static void constraint_free(struct constraint
*c
)
628 struct constraint
*next
= c
->next
? c
->next
: c
->union_next
;
635 static void constraint_extend(struct constraint
*c
, int pos
)
638 if (pos
< c
->v
->Size
)
641 v
= Vector_Alloc((3*c
->v
->Size
)/2);
642 Vector_Copy(c
->v
->p
, v
->p
, c
->v
->Size
);
647 static int evalue_read_constraint(struct stream
*s
, struct parameter
**p
,
648 struct constraint
**constraints
,
649 struct constraint
*union_next
)
652 struct constraint
*c
= NULL
;
654 while ((tok
= stream_next_token(s
))) {
657 if (tok
->type
== '+')
659 else if (tok
->type
== TOKEN_IDENT
) {
661 c
= constraint_new();
662 pos
= parameter_pos(p
, tok
->u
.s
, -1);
663 constraint_extend(c
, 1+pos
);
664 value_set_si(c
->v
->p
[1+pos
], 1);
666 } else if (tok
->type
== TOKEN_VALUE
) {
668 c
= constraint_new();
669 tok2
= stream_next_token(s
);
670 if (tok2
&& tok2
->type
== TOKEN_IDENT
) {
671 pos
= parameter_pos(p
, tok2
->u
.s
, -1);
672 constraint_extend(c
, 1+pos
);
673 value_assign(c
->v
->p
[1+pos
], tok
->u
.v
);
678 stream_push_token(s
, tok2
);
679 value_assign(c
->v
->p
[0], tok
->u
.v
);
682 } else if (tok
->type
== TOKEN_GE
|| tok
->type
== '=') {
683 int type
= tok
->type
== TOKEN_GE
;
685 tok
= stream_next_token(s
);
686 if (!tok
|| tok
->type
!= TOKEN_VALUE
|| value_notzero_p(tok
->u
.v
)) {
687 stream_error(s
, tok
, "expecting \"0\"");
689 stream_push_token(s
, tok
);
693 c
->next
= *constraints
;
694 c
->union_next
= union_next
;
701 stream_push_token(s
, tok
);
703 stream_error(s
, tok
, "unexpected token");
712 static struct constraint
*evalue_read_domain(struct stream
*s
, struct parameter
**p
,
715 struct constraint
*constraints
= NULL
;
716 struct constraint
*union_next
= NULL
;
720 tok
= stream_next_token(s
);
723 stream_push_token(s
, tok
);
726 while (evalue_read_constraint(s
, p
, &constraints
, union_next
)) {
727 tok
= stream_next_token(s
);
729 if (tok
->type
== TOKEN_UNION
) {
731 tok
= stream_next_token(s
);
733 stream_error(s
, NULL
, "unexpected EOF");
736 stream_push_token(s
, tok
);
737 union_next
= constraints
;
741 stream_push_token(s
, tok
);
742 /* empty line separates domain from evalue */
743 if (tok
->line
> line
+1)
753 struct constraint
*constraints
;
755 struct section
*next
;
758 static char **extract_parameters(struct parameter
*p
, unsigned *nparam
)
763 *nparam
= p
? p
->pos
+1 : 0;
764 params
= ALLOCN(char *, *nparam
);
765 for (i
= 0; i
< *nparam
; ++i
) {
766 struct parameter
*next
= p
->next
;
767 params
[p
->pos
] = p
->name
;
774 static Polyhedron
*constraints2domain(struct constraint
*constraints
,
775 unsigned nparam
, unsigned MaxRays
)
780 struct constraint
*c
;
781 struct constraint
*union_next
= NULL
;
783 for (n
= 0, c
= constraints
; c
; ++n
, c
= c
->next
)
785 M
= Matrix_Alloc(n
, 1+nparam
+1);
787 struct constraint
*next
= constraints
->next
;
788 union_next
= constraints
->union_next
;
789 Vector_Copy(constraints
->v
->p
+1, M
->p
[n
]+1, nparam
);
790 if (constraints
->type
)
791 value_set_si(M
->p
[n
][0], 1);
792 value_assign(M
->p
[n
][1+nparam
], constraints
->v
->p
[0]);
793 constraints
->next
= NULL
;
794 constraints
->union_next
= NULL
;
795 constraint_free(constraints
);
798 D
= Constraints2Polyhedron(M
, MaxRays
);
802 D
= DomainConcat(D
, constraints2domain(union_next
, nparam
, MaxRays
));
806 static evalue
*evalue_read_partition(struct stream
*s
, struct parameter
*p
,
808 unsigned *nparam
, unsigned MaxRays
)
810 struct section
*part
= NULL
;
811 struct constraint
*constraints
;
815 while ((constraints
= evalue_read_domain(s
, &p
, MaxRays
))) {
816 struct section
*sect
;
817 evalue
*e
= evalue_read_term(s
, &p
);
819 stream_error(s
, NULL
, "missing evalue");
822 sect
= ALLOC(struct section
);
823 sect
->constraints
= constraints
;
834 *ppp
= extract_parameters(p
, nparam
);
837 e
->x
.p
= new_enode(partition
, 2*m
, *nparam
);
839 for (j
= 0; j
< m
; ++j
) {
841 struct section
*next
= part
->next
;
842 constraints
= part
->constraints
;
843 D
= constraints2domain(part
->constraints
, *nparam
, MaxRays
);
844 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[2*(m
-j
-1)], D
);
845 value_clear(e
->x
.p
->arr
[2*(m
-j
-1)+1].d
);
846 e
->x
.p
->arr
[2*(m
-j
-1)+1] = *part
->e
;
855 static evalue
*evalue_read(struct stream
*s
, const char *var_list
, char ***ppp
,
856 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
860 struct parameter
*p
= NULL
;
865 while ((next
= strchr(var_list
, ','))) {
867 parameter_pos(&p
, var_list
, next
-var_list
);
870 if (strlen(var_list
) > 0)
871 parameter_pos(&p
, var_list
, -1);
872 nv
= p
? p
->pos
+1 : 0;
876 if (!(tok
= stream_next_token(s
)))
879 if (tok
->type
== TOKEN_VARS
) {
882 tok
= stream_next_token(s
);
883 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
884 stream_error(s
, tok
, "expecting identifier");
888 parameter_pos(&p
, tok
->u
.s
, -1);
890 tok
= stream_next_token(s
);
891 if (!tok
|| tok
->type
!= ',')
898 nv
= p
? p
->pos
+1 : 0;
901 if (tok
->type
== '(' || tok
->type
== '[') {
902 stream_push_token(s
, tok
);
903 e
= evalue_read_term(s
, &p
);
904 *ppp
= extract_parameters(p
, nparam
);
905 } else if (tok
->type
== TOKEN_VALUE
) {
906 struct token
*tok2
= stream_next_token(s
);
908 stream_push_token(s
, tok2
);
909 stream_push_token(s
, tok
);
910 if (tok2
&& (tok2
->type
== TOKEN_IDENT
|| tok2
->type
== TOKEN_GE
))
911 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
913 e
= evalue_read_term(s
, &p
);
914 *ppp
= extract_parameters(p
, nparam
);
916 } else if (tok
->type
== TOKEN_IDENT
) {
917 stream_push_token(s
, tok
);
918 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
920 stream_error(s
, tok
, "unexpected token");
921 *nparam
= nv
== -1 ? 0 : nv
;
932 evalue
*evalue_read_from_file(FILE *in
, const char *var_list
, char ***ppp
,
933 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
936 struct stream
*s
= stream_new_file(in
);
937 e
= evalue_read(s
, var_list
, ppp
, nvar
, nparam
, MaxRays
);
942 evalue
*evalue_read_from_str(const char *str
, const char *var_list
, char ***ppp
,
943 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
946 struct stream
*s
= stream_new_str(str
);
947 e
= evalue_read(s
, var_list
, ppp
, nvar
, nparam
, MaxRays
);