3 #include <barvinok/util.h>
4 #include "evalue_read.h"
6 #define ALLOC(type) (type*)malloc(sizeof(type))
7 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
9 enum token_type
{ TOKEN_UNKNOWN
= 256, TOKEN_VALUE
, TOKEN_IDENT
, TOKEN_GE
,
10 TOKEN_NE
, TOKEN_UNION
, TOKEN_VARS
};
15 unsigned int on_new_line
: 1;
25 static struct token
*token_new(int line
, int col
, unsigned on_new_line
)
27 struct token
*tok
= ALLOC(struct token
);
30 tok
->on_new_line
= on_new_line
;
34 void token_free(struct token
*tok
)
36 if (tok
->type
== TOKEN_VALUE
)
37 value_clear(tok
->u
.v
);
38 else if (tok
->type
== TOKEN_IDENT
)
55 struct token
*tokens
[5];
59 static struct stream
* stream_new()
62 struct stream
*s
= ALLOC(struct stream
);
66 s
->buffer
= (char*)malloc(s
->size
);
72 for (i
= 0; i
< 5; ++i
)
78 static struct stream
* stream_new_file(FILE *file
)
80 struct stream
*s
= stream_new();
85 static struct stream
* stream_new_str(const char *str
)
87 struct stream
*s
= stream_new();
92 static int stream_getc(struct stream
*s
)
117 static void stream_ungetc(struct stream
*s
, int c
)
126 static void stream_push_char(struct stream
*s
, int c
)
128 if (s
->len
>= s
->size
) {
129 s
->size
= (3*s
->size
)/2;
130 s
->buffer
= (char*)realloc(s
->buffer
, s
->size
);
132 s
->buffer
[s
->len
++] = c
;
135 static void stream_push_token(struct stream
*s
, struct token
*tok
)
137 assert(s
->n_token
< 5);
138 s
->tokens
[s
->n_token
++] = tok
;
141 static struct token
*stream_next_token(struct stream
*s
)
146 int old_line
= s
->line
;
149 return s
->tokens
[--s
->n_token
];
154 while ((c
= stream_getc(s
)) != -1 && isspace(c
))
176 tok
= token_new(line
, col
, old_line
!= line
);
177 tok
->type
= (enum token_type
)c
;
180 if (c
== '-' || isdigit(c
)) {
181 tok
= token_new(line
, col
, old_line
!= line
);
182 tok
->type
= TOKEN_VALUE
;
183 value_init(tok
->u
.v
);
184 stream_push_char(s
, c
);
185 while ((c
= stream_getc(s
)) != -1 && isdigit(c
))
186 stream_push_char(s
, c
);
189 if (s
->len
== 1 && s
->buffer
[0] == '-')
190 value_set_si(tok
->u
.v
, -1);
192 stream_push_char(s
, '\0');
193 mpz_set_str(tok
->u
.v
, s
->buffer
, 0);
197 if (c
== '#' || isalpha(c
)) {
198 tok
= token_new(line
, col
, old_line
!= line
);
199 stream_push_char(s
, c
);
200 while ((c
= stream_getc(s
)) != -1 && isalnum(c
))
201 stream_push_char(s
, c
);
204 stream_push_char(s
, '\0');
205 if (!strcmp(s
->buffer
, "#variables")) {
206 tok
->type
= TOKEN_VARS
;
207 } else if (s
->buffer
[0] == '#') {
208 tok
->type
= TOKEN_UNKNOWN
;
209 } else if (!strcmp(s
->buffer
, "UNION")) {
210 tok
->type
= TOKEN_UNION
;
212 tok
->type
= TOKEN_IDENT
;
213 tok
->u
.s
= strdup(s
->buffer
);
219 if ((c
= stream_getc(s
)) == '=') {
220 tok
= token_new(line
, col
, old_line
!= line
);
221 tok
->type
= TOKEN_GE
;
229 if ((c
= stream_getc(s
)) == '=') {
230 tok
= token_new(line
, col
, old_line
!= line
);
231 tok
->type
= TOKEN_NE
;
238 tok
= token_new(line
, col
, old_line
!= line
);
239 tok
->type
= TOKEN_UNKNOWN
;
243 void stream_error(struct stream
*s
, struct token
*tok
, char *msg
)
245 int line
= tok
? tok
->line
: s
->line
;
246 int col
= tok
? tok
->col
: s
->col
;
247 fprintf(stderr
, "syntax error (%d, %d): %s\n", line
, col
, msg
);
250 fprintf(stderr
, "got '%c'\n", tok
->type
);
252 fprintf(stderr
, "got token type %d\n", tok
->type
);
256 static void stream_free(struct stream
*s
)
259 if (s
->n_token
!= 0) {
260 struct token
*tok
= stream_next_token(s
);
261 stream_error(s
, tok
, "unexpected token");
269 struct parameter
*next
;
272 struct parameter
*parameter_new(const char *name
, int len
,
273 int pos
, struct parameter
*next
)
275 struct parameter
*p
= ALLOC(struct parameter
);
276 p
->name
= strdup(name
);
283 static int parameter_pos(struct parameter
**p
, const char *s
, int len
)
285 int pos
= *p
? (*p
)->pos
+1 : 0;
290 for (q
= *p
; q
; q
= q
->next
) {
291 if (strncmp(q
->name
, s
, len
) == 0 && q
->name
[len
] == '\0')
297 *p
= parameter_new(s
, len
, pos
, *p
);
301 static int optional_power(struct stream
*s
)
305 tok
= stream_next_token(s
);
308 if (tok
->type
!= '^') {
309 stream_push_token(s
, tok
);
313 tok
= stream_next_token(s
);
314 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
315 stream_error(s
, tok
, "expecting exponent");
317 stream_push_token(s
, tok
);
320 pow
= VALUE_TO_INT(tok
->u
.v
);
325 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
);
326 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
,
329 static evalue
*create_fract_like(struct stream
*s
, evalue
*arg
, enode_type type
,
330 struct parameter
**p
)
334 pow
= optional_power(s
);
338 e
->x
.p
= new_enode(type
, pow
+2, -1);
339 value_clear(e
->x
.p
->arr
[0].d
);
340 e
->x
.p
->arr
[0] = *arg
;
342 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 1, 1);
344 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 0, 1);
349 static evalue
*create_relation(evalue
*arg
, int ne
)
355 e
->x
.p
= new_enode(relation
, 2+ne
, 0);
356 value_clear(e
->x
.p
->arr
[0].d
);
357 e
->x
.p
->arr
[0] = *arg
;
360 evalue_set_si(&e
->x
.p
->arr
[1], 0, 1);
361 evalue_set_si(&e
->x
.p
->arr
[1+ne
], 1, 1);
366 static evalue
*read_fract(struct stream
*s
, struct token
*tok
, struct parameter
**p
)
370 tok
= stream_next_token(s
);
372 assert(tok
->type
== '{');
375 arg
= evalue_read_term(s
, p
, 1);
376 tok
= stream_next_token(s
);
377 if (!tok
|| tok
->type
!= '}') {
378 stream_error(s
, tok
, "expecting \"}\"");
380 stream_push_token(s
, tok
);
384 return create_fract_like(s
, arg
, fractional
, p
);
387 static evalue
*read_periodic(struct stream
*s
, struct parameter
**p
)
395 tok
= stream_next_token(s
);
396 assert(tok
&& tok
->type
== '[');
400 list
= (evalue
**)malloc(len
* sizeof(evalue
*));
404 evalue
*e
= evalue_read_term(s
, p
, 1);
406 stream_error(s
, NULL
, "missing argument or list element");
411 list
= (evalue
**)realloc(list
, len
* sizeof(evalue
*));
415 tok
= stream_next_token(s
);
417 stream_error(s
, NULL
, "unexpected EOF");
420 if (tok
->type
!= ',')
425 if (n
== 1 && (tok
->type
== '=' || tok
->type
== TOKEN_NE
)) {
426 int ne
= tok
->type
== TOKEN_NE
;
428 tok
= stream_next_token(s
);
429 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
430 stream_error(s
, tok
, "expecting \"0\"");
432 stream_push_token(s
, tok
);
436 tok
= stream_next_token(s
);
437 if (!tok
|| tok
->type
!= ']') {
438 stream_error(s
, tok
, "expecting \"]\"");
440 stream_push_token(s
, tok
);
444 e
= create_relation(list
[0], ne
);
449 if (tok
->type
!= ']') {
450 stream_error(s
, tok
, "expecting \"]\"");
451 stream_push_token(s
, tok
);
457 tok
= stream_next_token(s
);
458 if (tok
&& tok
->type
== '_') {
461 tok
= stream_next_token(s
);
462 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
463 stream_error(s
, tok
, "expecting identifier");
465 stream_push_token(s
, tok
);
470 pos
= parameter_pos(p
, tok
->u
.s
, -1);
472 e
->x
.p
= new_enode(periodic
, n
, pos
+1);
474 value_clear(e
->x
.p
->arr
[n
].d
);
475 e
->x
.p
->arr
[n
] = *list
[n
];
480 stream_push_token(s
, tok
);
481 e
= create_fract_like(s
, list
[0], flooring
, p
);
484 stream_error(s
, tok
, "unexpected token");
486 stream_push_token(s
, tok
);
491 evalue_free(list
[n
]);
496 /* frees product on error */
497 static evalue
*read_factor_and_multiply(struct stream
*s
, struct parameter
**p
,
501 e2
= evalue_read_factor(s
, p
);
503 stream_error(s
, NULL
, "unexpected EOF");
504 evalue_free(product
);
512 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
)
517 tok
= stream_next_token(s
);
521 if (tok
->type
== '(') {
523 e
= evalue_read_term(s
, p
, 1);
524 tok
= stream_next_token(s
);
525 if (!tok
|| tok
->type
!= ')') {
526 stream_error(s
, tok
, "expecting \")\"");
528 stream_push_token(s
, tok
);
531 } else if (tok
->type
== TOKEN_VALUE
) {
532 int line
= tok
->line
;
535 value_set_si(e
->d
, 1);
537 value_assign(e
->x
.n
, tok
->u
.v
);
539 tok
= stream_next_token(s
);
540 if (tok
&& tok
->type
== '/') {
542 tok
= stream_next_token(s
);
543 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
544 stream_error(s
, tok
, "expecting denominator");
546 stream_push_token(s
, tok
);
549 value_assign(e
->d
, tok
->u
.v
);
551 } else if (tok
&& tok
->type
== TOKEN_IDENT
&& tok
->line
== line
) {
552 stream_push_token(s
, tok
);
553 e
= read_factor_and_multiply(s
, p
, e
);
555 stream_push_token(s
, tok
);
556 } else if (tok
->type
== TOKEN_IDENT
) {
557 int pos
= parameter_pos(p
, tok
->u
.s
, -1);
558 int pow
= optional_power(s
);
562 e
->x
.p
= new_enode(polynomial
, pow
+1, pos
+1);
563 evalue_set_si(&e
->x
.p
->arr
[pow
], 1, 1);
565 evalue_set_si(&e
->x
.p
->arr
[pow
], 0, 1);
566 } else if (tok
->type
== '[') {
567 stream_push_token(s
, tok
);
568 e
= read_periodic(s
, p
);
569 } else if (tok
->type
== '{') {
570 stream_push_token(s
, tok
);
571 e
= read_fract(s
, tok
, p
);
574 tok
= stream_next_token(s
);
575 if (tok
&& tok
->type
== '*') {
577 e
= read_factor_and_multiply(s
, p
, e
);
579 stream_push_token(s
, tok
);
584 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
,
590 e
= evalue_read_factor(s
, p
);
594 tok
= stream_next_token(s
);
598 if (!multi_line
&& tok
->on_new_line
)
599 stream_push_token(s
, tok
);
600 else if (tok
->type
== '+' || tok
->type
== TOKEN_VALUE
) {
602 if (tok
->type
== '+')
605 stream_push_token(s
, tok
);
606 e2
= evalue_read_term(s
, p
, multi_line
);
608 stream_error(s
, NULL
, "unexpected EOF");
614 stream_push_token(s
, tok
);
622 struct constraint
*next
;
623 struct constraint
*union_next
;
626 static struct constraint
*constraint_new()
628 struct constraint
*c
= ALLOC(struct constraint
);
630 c
->v
= Vector_Alloc(16);
632 c
->union_next
= NULL
;
636 static void constraint_free(struct constraint
*c
)
639 struct constraint
*next
= c
->next
? c
->next
: c
->union_next
;
646 static void constraint_extend(struct constraint
*c
, int pos
)
649 if (pos
< c
->v
->Size
)
652 v
= Vector_Alloc((3*c
->v
->Size
)/2);
653 Vector_Copy(c
->v
->p
, v
->p
, c
->v
->Size
);
658 static int evalue_read_constraint(struct stream
*s
, struct parameter
**p
,
659 struct constraint
**constraints
,
660 struct constraint
*union_next
)
663 struct constraint
*c
= NULL
;
665 while ((tok
= stream_next_token(s
))) {
668 if (tok
->type
== '+')
670 else if (tok
->type
== TOKEN_IDENT
) {
672 c
= constraint_new();
673 pos
= parameter_pos(p
, tok
->u
.s
, -1);
674 constraint_extend(c
, 1+pos
);
675 value_set_si(c
->v
->p
[1+pos
], 1);
677 } else if (tok
->type
== TOKEN_VALUE
) {
679 c
= constraint_new();
680 tok2
= stream_next_token(s
);
681 if (tok2
&& tok2
->type
== TOKEN_VALUE
) {
682 /* Handle "-" space cst, where "-" is translated to -1 */
683 value_multiply(tok
->u
.v
, tok
->u
.v
, tok2
->u
.v
);
685 tok2
= stream_next_token(s
);
687 if (tok2
&& tok2
->type
== TOKEN_IDENT
) {
688 pos
= parameter_pos(p
, tok2
->u
.s
, -1);
689 constraint_extend(c
, 1+pos
);
690 value_assign(c
->v
->p
[1+pos
], tok
->u
.v
);
695 stream_push_token(s
, tok2
);
696 value_assign(c
->v
->p
[0], tok
->u
.v
);
699 } else if (tok
->type
== TOKEN_GE
|| tok
->type
== '=') {
700 int type
= tok
->type
== TOKEN_GE
;
702 tok
= stream_next_token(s
);
703 if (!tok
|| tok
->type
!= TOKEN_VALUE
|| value_notzero_p(tok
->u
.v
)) {
704 stream_error(s
, tok
, "expecting \"0\"");
706 stream_push_token(s
, tok
);
710 stream_error(s
, NULL
, "empty constraint");
714 c
->next
= *constraints
;
715 c
->union_next
= union_next
;
723 stream_push_token(s
, tok
);
725 stream_error(s
, tok
, "unexpected token");
734 static struct constraint
*evalue_read_domain(struct stream
*s
, struct parameter
**p
,
737 struct constraint
*constraints
= NULL
;
738 struct constraint
*union_next
= NULL
;
742 tok
= stream_next_token(s
);
745 stream_push_token(s
, tok
);
748 while (evalue_read_constraint(s
, p
, &constraints
, union_next
)) {
749 tok
= stream_next_token(s
);
751 if (tok
->type
== TOKEN_UNION
) {
753 tok
= stream_next_token(s
);
755 stream_error(s
, NULL
, "unexpected EOF");
758 stream_push_token(s
, tok
);
759 union_next
= constraints
;
763 stream_push_token(s
, tok
);
764 /* empty line separates domain from evalue */
765 if (tok
->line
> line
+1)
775 struct constraint
*constraints
;
777 struct section
*next
;
780 static const char **extract_parameters(struct parameter
*p
, unsigned *nparam
)
785 *nparam
= p
? p
->pos
+1 : 0;
786 params
= ALLOCN(const char *, *nparam
);
787 for (i
= 0; i
< *nparam
; ++i
) {
788 struct parameter
*next
= p
->next
;
789 params
[p
->pos
] = p
->name
;
796 static Polyhedron
*constraints2domain(struct constraint
*constraints
,
797 unsigned nparam
, unsigned MaxRays
)
802 struct constraint
*c
;
803 struct constraint
*union_next
= NULL
;
805 for (n
= 0, c
= constraints
; c
; ++n
, c
= c
->next
)
807 M
= Matrix_Alloc(n
, 1+nparam
+1);
809 struct constraint
*next
= constraints
->next
;
810 union_next
= constraints
->union_next
;
811 Vector_Copy(constraints
->v
->p
+1, M
->p
[n
]+1, nparam
);
812 if (constraints
->type
)
813 value_set_si(M
->p
[n
][0], 1);
814 value_assign(M
->p
[n
][1+nparam
], constraints
->v
->p
[0]);
815 constraints
->next
= NULL
;
816 constraints
->union_next
= NULL
;
817 constraint_free(constraints
);
820 D
= Constraints2Polyhedron(M
, MaxRays
);
824 D
= DomainConcat(D
, constraints2domain(union_next
, nparam
, MaxRays
));
828 static evalue
*evalue_read_partition(struct stream
*s
, struct parameter
*p
,
830 unsigned *nparam
, unsigned MaxRays
)
832 struct section
*part
= NULL
;
833 struct constraint
*constraints
;
837 while ((constraints
= evalue_read_domain(s
, &p
, MaxRays
))) {
838 struct section
*sect
;
839 evalue
*e
= evalue_read_term(s
, &p
, 0);
841 stream_error(s
, NULL
, "missing evalue");
844 sect
= ALLOC(struct section
);
845 sect
->constraints
= constraints
;
856 *ppp
= extract_parameters(p
, nparam
);
859 e
->x
.p
= new_enode(partition
, 2*m
, *nparam
);
861 for (j
= 0; j
< m
; ++j
) {
863 struct section
*next
= part
->next
;
864 constraints
= part
->constraints
;
865 D
= constraints2domain(part
->constraints
, *nparam
, MaxRays
);
866 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[2*(m
-j
-1)], D
);
867 value_clear(e
->x
.p
->arr
[2*(m
-j
-1)+1].d
);
868 e
->x
.p
->arr
[2*(m
-j
-1)+1] = *part
->e
;
877 static evalue
*evalue_read(struct stream
*s
, const char *var_list
,
879 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
883 struct parameter
*p
= NULL
;
888 while ((next
= strchr(var_list
, ','))) {
890 parameter_pos(&p
, var_list
, next
-var_list
);
893 if (strlen(var_list
) > 0)
894 parameter_pos(&p
, var_list
, -1);
895 nv
= p
? p
->pos
+1 : 0;
899 if (!(tok
= stream_next_token(s
)))
902 if (tok
->type
== TOKEN_VARS
) {
905 tok
= stream_next_token(s
);
906 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
907 stream_error(s
, tok
, "expecting identifier");
911 parameter_pos(&p
, tok
->u
.s
, -1);
913 tok
= stream_next_token(s
);
914 if (!tok
|| tok
->type
!= ',')
921 nv
= p
? p
->pos
+1 : 0;
924 if (tok
->type
== '(' || tok
->type
== '[') {
925 stream_push_token(s
, tok
);
926 e
= evalue_read_term(s
, &p
, 0);
927 *ppp
= extract_parameters(p
, nparam
);
928 } else if (tok
->type
== TOKEN_VALUE
) {
929 struct token
*tok2
= stream_next_token(s
);
931 stream_push_token(s
, tok2
);
932 stream_push_token(s
, tok
);
933 if (tok2
&& (tok2
->type
== TOKEN_IDENT
|| tok2
->type
== TOKEN_GE
))
934 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
936 e
= evalue_read_term(s
, &p
, 0);
937 *ppp
= extract_parameters(p
, nparam
);
939 } else if (tok
->type
== TOKEN_IDENT
) {
940 stream_push_token(s
, tok
);
941 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
943 stream_error(s
, tok
, "unexpected token");
944 *nparam
= nv
== -1 ? 0 : nv
;
955 evalue
*evalue_read_from_file(FILE *in
, const char *var_list
,
957 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
960 struct stream
*s
= stream_new_file(in
);
961 e
= evalue_read(s
, var_list
, ppp
, nvar
, nparam
, MaxRays
);
966 evalue
*evalue_read_from_str(const char *str
, const char *var_list
,
968 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
971 struct stream
*s
= stream_new_str(str
);
972 e
= evalue_read(s
, var_list
, ppp
, nvar
, nparam
, MaxRays
);