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
};
14 unsigned int on_new_line
: 1;
24 static struct token
*token_new(int line
, int col
, unsigned on_new_line
)
26 struct token
*tok
= ALLOC(struct token
);
29 tok
->on_new_line
= on_new_line
;
33 void token_free(struct token
*tok
)
35 if (tok
->type
== TOKEN_VALUE
)
36 value_clear(tok
->u
.v
);
37 else if (tok
->type
== TOKEN_IDENT
)
54 struct token
*tokens
[5];
58 static struct stream
* stream_new()
61 struct stream
*s
= ALLOC(struct stream
);
65 s
->buffer
= (char*)malloc(s
->size
);
71 for (i
= 0; i
< 5; ++i
)
77 static struct stream
* stream_new_file(FILE *file
)
79 struct stream
*s
= stream_new();
84 static struct stream
* stream_new_str(const char *str
)
86 struct stream
*s
= stream_new();
91 static int stream_getc(struct stream
*s
)
116 static void stream_ungetc(struct stream
*s
, int c
)
125 static void stream_push_char(struct stream
*s
, int c
)
127 if (s
->len
>= s
->size
) {
128 s
->size
= (3*s
->size
)/2;
129 s
->buffer
= (char*)realloc(s
->buffer
, s
->size
);
131 s
->buffer
[s
->len
++] = c
;
134 static struct token
*stream_push_token(struct stream
*s
, struct token
*tok
)
136 assert(s
->n_token
< 5);
137 s
->tokens
[s
->n_token
++] = tok
;
140 static struct token
*stream_next_token(struct stream
*s
)
145 int old_line
= s
->line
;
148 return s
->tokens
[--s
->n_token
];
153 while ((c
= stream_getc(s
)) != -1 && isspace(c
))
175 tok
= token_new(line
, col
, old_line
!= line
);
176 tok
->type
= (enum token_type
)c
;
179 if (c
== '-' || isdigit(c
)) {
180 tok
= token_new(line
, col
, old_line
!= line
);
181 tok
->type
= TOKEN_VALUE
;
182 value_init(tok
->u
.v
);
183 stream_push_char(s
, c
);
184 while ((c
= stream_getc(s
)) != -1 && isdigit(c
))
185 stream_push_char(s
, c
);
188 if (s
->len
== 1 && s
->buffer
[0] == '-')
189 value_set_si(tok
->u
.v
, -1);
191 stream_push_char(s
, '\0');
192 mpz_set_str(tok
->u
.v
, s
->buffer
, 0);
196 if (c
== '#' || isalpha(c
)) {
197 tok
= token_new(line
, col
, old_line
!= line
);
198 stream_push_char(s
, c
);
199 while ((c
= stream_getc(s
)) != -1 && isalnum(c
))
200 stream_push_char(s
, c
);
203 stream_push_char(s
, '\0');
204 if (!strcmp(s
->buffer
, "#variables")) {
205 tok
->type
= TOKEN_VARS
;
206 } else if (s
->buffer
[0] == '#') {
207 tok
->type
= TOKEN_UNKNOWN
;
208 } else if (!strcmp(s
->buffer
, "UNION")) {
209 tok
->type
= TOKEN_UNION
;
211 tok
->type
= TOKEN_IDENT
;
212 tok
->u
.s
= strdup(s
->buffer
);
218 if ((c
= stream_getc(s
)) == '=') {
219 tok
= token_new(line
, col
, old_line
!= line
);
220 tok
->type
= TOKEN_GE
;
228 if ((c
= stream_getc(s
)) == '=') {
229 tok
= token_new(line
, col
, old_line
!= line
);
230 tok
->type
= TOKEN_NE
;
237 tok
= token_new(line
, col
, old_line
!= line
);
238 tok
->type
= TOKEN_UNKNOWN
;
242 void stream_error(struct stream
*s
, struct token
*tok
, char *msg
)
244 int line
= tok
? tok
->line
: s
->line
;
245 int col
= tok
? tok
->col
: s
->col
;
246 fprintf(stderr
, "syntax error (%d, %d): %s\n", line
, col
, msg
);
249 fprintf(stderr
, "got '%c'\n", tok
->type
);
251 fprintf(stderr
, "got token type %d\n", tok
->type
);
255 static void stream_free(struct stream
*s
)
258 if (s
->n_token
!= 0) {
259 struct token
*tok
= stream_next_token(s
);
260 stream_error(s
, tok
, "unexpected token");
268 struct parameter
*next
;
271 struct parameter
*parameter_new(const char *name
, int len
,
272 int pos
, struct parameter
*next
)
274 struct parameter
*p
= ALLOC(struct parameter
);
275 p
->name
= strdup(name
);
282 static int parameter_pos(struct parameter
**p
, const char *s
, int len
)
284 int pos
= *p
? (*p
)->pos
+1 : 0;
289 for (q
= *p
; q
; q
= q
->next
) {
290 if (strncmp(q
->name
, s
, len
) == 0 && q
->name
[len
] == '\0')
296 *p
= parameter_new(s
, len
, pos
, *p
);
300 static int optional_power(struct stream
*s
)
304 tok
= stream_next_token(s
);
307 if (tok
->type
!= '^') {
308 stream_push_token(s
, tok
);
312 tok
= stream_next_token(s
);
313 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
314 stream_error(s
, tok
, "expecting exponent");
316 stream_push_token(s
, tok
);
319 pow
= VALUE_TO_INT(tok
->u
.v
);
324 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
);
325 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
,
328 static evalue
*create_fract_like(struct stream
*s
, evalue
*arg
, enode_type type
,
329 struct parameter
**p
)
333 pow
= optional_power(s
);
337 e
->x
.p
= new_enode(type
, pow
+2, -1);
338 value_clear(e
->x
.p
->arr
[0].d
);
339 e
->x
.p
->arr
[0] = *arg
;
341 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 1, 1);
343 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 0, 1);
348 static evalue
*create_relation(evalue
*arg
, int ne
)
354 e
->x
.p
= new_enode(relation
, 2+ne
, 0);
355 value_clear(e
->x
.p
->arr
[0].d
);
356 e
->x
.p
->arr
[0] = *arg
;
359 evalue_set_si(&e
->x
.p
->arr
[1], 0, 1);
360 evalue_set_si(&e
->x
.p
->arr
[1+ne
], 1, 1);
365 static evalue
*read_fract(struct stream
*s
, struct token
*tok
, struct parameter
**p
)
369 tok
= stream_next_token(s
);
371 assert(tok
->type
== '{');
374 arg
= evalue_read_term(s
, p
, 1);
375 tok
= stream_next_token(s
);
376 if (!tok
|| tok
->type
!= '}') {
377 stream_error(s
, tok
, "expecting \"}\"");
379 stream_push_token(s
, tok
);
383 return create_fract_like(s
, arg
, fractional
, p
);
386 static evalue
*read_periodic(struct stream
*s
, struct parameter
**p
)
394 tok
= stream_next_token(s
);
395 assert(tok
&& tok
->type
== '[');
399 list
= (evalue
**)malloc(len
* sizeof(evalue
*));
403 evalue
*e
= evalue_read_term(s
, p
, 1);
405 stream_error(s
, NULL
, "missing argument or list element");
410 list
= (evalue
**)realloc(list
, len
* sizeof(evalue
*));
414 tok
= stream_next_token(s
);
416 stream_error(s
, NULL
, "unexpected EOF");
419 if (tok
->type
!= ',')
424 if (n
== 1 && (tok
->type
== '=' || tok
->type
== TOKEN_NE
)) {
425 int ne
= tok
->type
== TOKEN_NE
;
427 tok
= stream_next_token(s
);
428 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
429 stream_error(s
, tok
, "expecting \"0\"");
431 stream_push_token(s
, tok
);
435 tok
= stream_next_token(s
);
436 if (!tok
|| tok
->type
!= ']') {
437 stream_error(s
, tok
, "expecting \"]\"");
439 stream_push_token(s
, tok
);
443 e
= create_relation(list
[0], ne
);
448 if (tok
->type
!= ']') {
449 stream_error(s
, tok
, "expecting \"]\"");
450 stream_push_token(s
, tok
);
456 tok
= stream_next_token(s
);
457 if (tok
&& tok
->type
== '_') {
460 tok
= stream_next_token(s
);
461 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
462 stream_error(s
, tok
, "expecting identifier");
464 stream_push_token(s
, tok
);
469 pos
= parameter_pos(p
, tok
->u
.s
, -1);
471 e
->x
.p
= new_enode(periodic
, n
, pos
+1);
473 value_clear(e
->x
.p
->arr
[n
].d
);
474 e
->x
.p
->arr
[n
] = *list
[n
];
479 stream_push_token(s
, tok
);
480 e
= create_fract_like(s
, list
[0], flooring
, p
);
483 stream_error(s
, tok
, "unexpected token");
485 stream_push_token(s
, tok
);
490 evalue_free(list
[n
]);
495 /* frees product on error */
496 static evalue
*read_factor_and_multiply(struct stream
*s
, struct parameter
**p
,
500 e2
= evalue_read_factor(s
, p
);
502 stream_error(s
, NULL
, "unexpected EOF");
503 evalue_free(product
);
511 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
)
516 tok
= stream_next_token(s
);
520 if (tok
->type
== '(') {
522 e
= evalue_read_term(s
, p
, 1);
523 tok
= stream_next_token(s
);
524 if (!tok
|| tok
->type
!= ')') {
525 stream_error(s
, tok
, "expecting \")\"");
527 stream_push_token(s
, tok
);
530 } else if (tok
->type
== TOKEN_VALUE
) {
531 int line
= tok
->line
;
534 value_set_si(e
->d
, 1);
536 value_assign(e
->x
.n
, tok
->u
.v
);
538 tok
= stream_next_token(s
);
539 if (tok
&& tok
->type
== '/') {
541 tok
= stream_next_token(s
);
542 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
543 stream_error(s
, tok
, "expecting denominator");
545 stream_push_token(s
, tok
);
548 value_assign(e
->d
, tok
->u
.v
);
550 } else if (tok
&& tok
->type
== TOKEN_IDENT
&& tok
->line
== line
) {
551 stream_push_token(s
, tok
);
552 e
= read_factor_and_multiply(s
, p
, e
);
554 stream_push_token(s
, tok
);
555 } else if (tok
->type
== TOKEN_IDENT
) {
556 int pos
= parameter_pos(p
, tok
->u
.s
, -1);
557 int pow
= optional_power(s
);
561 e
->x
.p
= new_enode(polynomial
, pow
+1, pos
+1);
562 evalue_set_si(&e
->x
.p
->arr
[pow
], 1, 1);
564 evalue_set_si(&e
->x
.p
->arr
[pow
], 0, 1);
565 } else if (tok
->type
== '[') {
566 stream_push_token(s
, tok
);
567 e
= read_periodic(s
, p
);
568 } else if (tok
->type
== '{') {
569 stream_push_token(s
, tok
);
570 e
= read_fract(s
, tok
, p
);
573 tok
= stream_next_token(s
);
574 if (tok
&& tok
->type
== '*') {
576 e
= read_factor_and_multiply(s
, p
, e
);
578 stream_push_token(s
, tok
);
583 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
,
589 e
= evalue_read_factor(s
, p
);
593 tok
= stream_next_token(s
);
597 if (!multi_line
&& tok
->on_new_line
)
598 stream_push_token(s
, tok
);
599 else if (tok
->type
== '+' || tok
->type
== TOKEN_VALUE
) {
601 if (tok
->type
== '+')
604 stream_push_token(s
, tok
);
605 e2
= evalue_read_term(s
, p
, multi_line
);
607 stream_error(s
, NULL
, "unexpected EOF");
613 stream_push_token(s
, tok
);
621 struct constraint
*next
;
622 struct constraint
*union_next
;
625 static struct constraint
*constraint_new()
627 struct constraint
*c
= ALLOC(struct constraint
);
629 c
->v
= Vector_Alloc(16);
631 c
->union_next
= NULL
;
635 static void constraint_free(struct constraint
*c
)
638 struct constraint
*next
= c
->next
? c
->next
: c
->union_next
;
645 static void constraint_extend(struct constraint
*c
, int pos
)
648 if (pos
< c
->v
->Size
)
651 v
= Vector_Alloc((3*c
->v
->Size
)/2);
652 Vector_Copy(c
->v
->p
, v
->p
, c
->v
->Size
);
657 static int evalue_read_constraint(struct stream
*s
, struct parameter
**p
,
658 struct constraint
**constraints
,
659 struct constraint
*union_next
)
662 struct constraint
*c
= NULL
;
664 while ((tok
= stream_next_token(s
))) {
667 if (tok
->type
== '+')
669 else if (tok
->type
== TOKEN_IDENT
) {
671 c
= constraint_new();
672 pos
= parameter_pos(p
, tok
->u
.s
, -1);
673 constraint_extend(c
, 1+pos
);
674 value_set_si(c
->v
->p
[1+pos
], 1);
676 } else if (tok
->type
== TOKEN_VALUE
) {
678 c
= constraint_new();
679 tok2
= stream_next_token(s
);
680 if (tok2
&& tok2
->type
== TOKEN_VALUE
) {
681 /* Handle "-" space cst, where "-" is translated to -1 */
682 value_multiply(tok
->u
.v
, tok
->u
.v
, tok2
->u
.v
);
684 tok2
= stream_next_token(s
);
686 if (tok2
&& tok2
->type
== TOKEN_IDENT
) {
687 pos
= parameter_pos(p
, tok2
->u
.s
, -1);
688 constraint_extend(c
, 1+pos
);
689 value_assign(c
->v
->p
[1+pos
], tok
->u
.v
);
694 stream_push_token(s
, tok2
);
695 value_assign(c
->v
->p
[0], tok
->u
.v
);
698 } else if (tok
->type
== TOKEN_GE
|| tok
->type
== '=') {
699 int type
= tok
->type
== TOKEN_GE
;
701 tok
= stream_next_token(s
);
702 if (!tok
|| tok
->type
!= TOKEN_VALUE
|| value_notzero_p(tok
->u
.v
)) {
703 stream_error(s
, tok
, "expecting \"0\"");
705 stream_push_token(s
, tok
);
709 stream_error(s
, NULL
, "empty constraint");
713 c
->next
= *constraints
;
714 c
->union_next
= union_next
;
722 stream_push_token(s
, tok
);
724 stream_error(s
, tok
, "unexpected token");
733 static struct constraint
*evalue_read_domain(struct stream
*s
, struct parameter
**p
,
736 struct constraint
*constraints
= NULL
;
737 struct constraint
*union_next
= NULL
;
741 tok
= stream_next_token(s
);
744 stream_push_token(s
, tok
);
747 while (evalue_read_constraint(s
, p
, &constraints
, union_next
)) {
748 tok
= stream_next_token(s
);
750 if (tok
->type
== TOKEN_UNION
) {
752 tok
= stream_next_token(s
);
754 stream_error(s
, NULL
, "unexpected EOF");
757 stream_push_token(s
, tok
);
758 union_next
= constraints
;
762 stream_push_token(s
, tok
);
763 /* empty line separates domain from evalue */
764 if (tok
->line
> line
+1)
774 struct constraint
*constraints
;
776 struct section
*next
;
779 static const char **extract_parameters(struct parameter
*p
, unsigned *nparam
)
784 *nparam
= p
? p
->pos
+1 : 0;
785 params
= ALLOCN(const char *, *nparam
);
786 for (i
= 0; i
< *nparam
; ++i
) {
787 struct parameter
*next
= p
->next
;
788 params
[p
->pos
] = p
->name
;
795 static Polyhedron
*constraints2domain(struct constraint
*constraints
,
796 unsigned nparam
, unsigned MaxRays
)
801 struct constraint
*c
;
802 struct constraint
*union_next
= NULL
;
804 for (n
= 0, c
= constraints
; c
; ++n
, c
= c
->next
)
806 M
= Matrix_Alloc(n
, 1+nparam
+1);
808 struct constraint
*next
= constraints
->next
;
809 union_next
= constraints
->union_next
;
810 Vector_Copy(constraints
->v
->p
+1, M
->p
[n
]+1, nparam
);
811 if (constraints
->type
)
812 value_set_si(M
->p
[n
][0], 1);
813 value_assign(M
->p
[n
][1+nparam
], constraints
->v
->p
[0]);
814 constraints
->next
= NULL
;
815 constraints
->union_next
= NULL
;
816 constraint_free(constraints
);
819 D
= Constraints2Polyhedron(M
, MaxRays
);
823 D
= DomainConcat(D
, constraints2domain(union_next
, nparam
, MaxRays
));
827 static evalue
*evalue_read_partition(struct stream
*s
, struct parameter
*p
,
829 unsigned *nparam
, unsigned MaxRays
)
831 struct section
*part
= NULL
;
832 struct constraint
*constraints
;
836 while ((constraints
= evalue_read_domain(s
, &p
, MaxRays
))) {
837 struct section
*sect
;
838 evalue
*e
= evalue_read_term(s
, &p
, 0);
840 stream_error(s
, NULL
, "missing evalue");
843 sect
= ALLOC(struct section
);
844 sect
->constraints
= constraints
;
855 *ppp
= extract_parameters(p
, nparam
);
858 e
->x
.p
= new_enode(partition
, 2*m
, *nparam
);
860 for (j
= 0; j
< m
; ++j
) {
862 struct section
*next
= part
->next
;
863 constraints
= part
->constraints
;
864 D
= constraints2domain(part
->constraints
, *nparam
, MaxRays
);
865 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[2*(m
-j
-1)], D
);
866 value_clear(e
->x
.p
->arr
[2*(m
-j
-1)+1].d
);
867 e
->x
.p
->arr
[2*(m
-j
-1)+1] = *part
->e
;
876 static evalue
*evalue_read(struct stream
*s
, const char *var_list
,
878 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
882 struct parameter
*p
= NULL
;
887 while ((next
= strchr(var_list
, ','))) {
889 parameter_pos(&p
, var_list
, next
-var_list
);
892 if (strlen(var_list
) > 0)
893 parameter_pos(&p
, var_list
, -1);
894 nv
= p
? p
->pos
+1 : 0;
898 if (!(tok
= stream_next_token(s
)))
901 if (tok
->type
== TOKEN_VARS
) {
904 tok
= stream_next_token(s
);
905 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
906 stream_error(s
, tok
, "expecting identifier");
910 parameter_pos(&p
, tok
->u
.s
, -1);
912 tok
= stream_next_token(s
);
913 if (!tok
|| tok
->type
!= ',')
920 nv
= p
? p
->pos
+1 : 0;
923 if (tok
->type
== '(' || tok
->type
== '[') {
924 stream_push_token(s
, tok
);
925 e
= evalue_read_term(s
, &p
, 0);
926 *ppp
= extract_parameters(p
, nparam
);
927 } else if (tok
->type
== TOKEN_VALUE
) {
928 struct token
*tok2
= stream_next_token(s
);
930 stream_push_token(s
, tok2
);
931 stream_push_token(s
, tok
);
932 if (tok2
&& (tok2
->type
== TOKEN_IDENT
|| tok2
->type
== TOKEN_GE
))
933 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
935 e
= evalue_read_term(s
, &p
, 0);
936 *ppp
= extract_parameters(p
, nparam
);
938 } else if (tok
->type
== TOKEN_IDENT
) {
939 stream_push_token(s
, tok
);
940 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
942 stream_error(s
, tok
, "unexpected token");
943 *nparam
= nv
== -1 ? 0 : nv
;
954 evalue
*evalue_read_from_file(FILE *in
, const char *var_list
,
956 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
959 struct stream
*s
= stream_new_file(in
);
960 e
= evalue_read(s
, var_list
, ppp
, nvar
, nparam
, MaxRays
);
965 evalue
*evalue_read_from_str(const char *str
, const char *var_list
,
967 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
970 struct stream
*s
= stream_new_str(str
);
971 e
= evalue_read(s
, var_list
, ppp
, nvar
, nparam
, MaxRays
);