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
);
217 if ((c
= stream_getc(s
)) == '=') {
218 tok
= token_new(line
, col
, old_line
!= line
);
219 tok
->type
= TOKEN_GE
;
226 if ((c
= stream_getc(s
)) == '=') {
227 tok
= token_new(line
, col
, old_line
!= line
);
228 tok
->type
= TOKEN_NE
;
235 tok
= token_new(line
, col
, old_line
!= line
);
236 tok
->type
= TOKEN_UNKNOWN
;
240 void stream_error(struct stream
*s
, struct token
*tok
, char *msg
)
242 int line
= tok
? tok
->line
: s
->line
;
243 int col
= tok
? tok
->col
: s
->col
;
244 fprintf(stderr
, "syntax error (%d, %d): %s\n", line
, col
, msg
);
247 fprintf(stderr
, "got '%c'\n", tok
->type
);
249 fprintf(stderr
, "got token type %d\n", tok
->type
);
253 static void stream_free(struct stream
*s
)
256 if (s
->n_token
!= 0) {
257 struct token
*tok
= stream_next_token(s
);
258 stream_error(s
, tok
, "unexpected token");
266 struct parameter
*next
;
269 struct parameter
*parameter_new(const char *name
, int len
,
270 int pos
, struct parameter
*next
)
272 struct parameter
*p
= ALLOC(struct parameter
);
273 p
->name
= strdup(name
);
280 static int parameter_pos(struct parameter
**p
, const char *s
, int len
)
282 int pos
= *p
? (*p
)->pos
+1 : 0;
287 for (q
= *p
; q
; q
= q
->next
) {
288 if (strncmp(q
->name
, s
, len
) == 0 && q
->name
[len
] == '\0')
294 *p
= parameter_new(s
, len
, pos
, *p
);
298 static int optional_power(struct stream
*s
)
302 tok
= stream_next_token(s
);
305 if (tok
->type
!= '^') {
306 stream_push_token(s
, tok
);
310 tok
= stream_next_token(s
);
311 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
312 stream_error(s
, tok
, "expecting exponent");
314 stream_push_token(s
, tok
);
317 pow
= VALUE_TO_INT(tok
->u
.v
);
322 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
);
323 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
,
326 static evalue
*create_fract_like(struct stream
*s
, evalue
*arg
, enode_type type
,
327 struct parameter
**p
)
331 pow
= optional_power(s
);
335 e
->x
.p
= new_enode(type
, pow
+2, -1);
336 value_clear(e
->x
.p
->arr
[0].d
);
337 e
->x
.p
->arr
[0] = *arg
;
339 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 1, 1);
341 evalue_set_si(&e
->x
.p
->arr
[1+pow
], 0, 1);
346 static evalue
*create_relation(evalue
*arg
, int ne
)
352 e
->x
.p
= new_enode(relation
, 2+ne
, 0);
353 value_clear(e
->x
.p
->arr
[0].d
);
354 e
->x
.p
->arr
[0] = *arg
;
357 evalue_set_si(&e
->x
.p
->arr
[1], 0, 1);
358 evalue_set_si(&e
->x
.p
->arr
[1+ne
], 1, 1);
363 static evalue
*read_fract(struct stream
*s
, struct token
*tok
, struct parameter
**p
)
367 tok
= stream_next_token(s
);
369 assert(tok
->type
== '{');
372 arg
= evalue_read_term(s
, p
, 1);
373 tok
= stream_next_token(s
);
374 if (!tok
|| tok
->type
!= '}') {
375 stream_error(s
, tok
, "expecting \"}\"");
377 stream_push_token(s
, tok
);
381 return create_fract_like(s
, arg
, fractional
, p
);
384 static evalue
*read_periodic(struct stream
*s
, struct parameter
**p
)
392 tok
= stream_next_token(s
);
393 assert(tok
&& tok
->type
== '[');
397 list
= (evalue
**)malloc(len
* sizeof(evalue
*));
401 evalue
*e
= evalue_read_term(s
, p
, 1);
403 stream_error(s
, NULL
, "missing argument or list element");
408 list
= (evalue
**)realloc(list
, len
* sizeof(evalue
*));
412 tok
= stream_next_token(s
);
414 stream_error(s
, NULL
, "unexpected EOF");
417 if (tok
->type
!= ',')
422 if (n
== 1 && (tok
->type
== '=' || tok
->type
== TOKEN_NE
)) {
423 int ne
= tok
->type
== TOKEN_NE
;
425 tok
= stream_next_token(s
);
426 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
427 stream_error(s
, tok
, "expecting \"0\"");
429 stream_push_token(s
, tok
);
433 tok
= stream_next_token(s
);
434 if (!tok
|| tok
->type
!= ']') {
435 stream_error(s
, tok
, "expecting \"]\"");
437 stream_push_token(s
, tok
);
441 e
= create_relation(list
[0], ne
);
446 if (tok
->type
!= ']') {
447 stream_error(s
, tok
, "expecting \"]\"");
448 stream_push_token(s
, tok
);
454 tok
= stream_next_token(s
);
455 if (tok
&& tok
->type
== '_') {
458 tok
= stream_next_token(s
);
459 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
460 stream_error(s
, tok
, "expecting identifier");
462 stream_push_token(s
, tok
);
467 pos
= parameter_pos(p
, tok
->u
.s
, -1);
469 e
->x
.p
= new_enode(periodic
, n
, pos
+1);
471 value_clear(e
->x
.p
->arr
[n
].d
);
472 e
->x
.p
->arr
[n
] = *list
[n
];
477 stream_push_token(s
, tok
);
478 e
= create_fract_like(s
, list
[0], flooring
, p
);
481 stream_error(s
, tok
, "unexpected token");
483 stream_push_token(s
, tok
);
488 evalue_free(list
[n
]);
493 /* frees product on error */
494 static evalue
*read_factor_and_multiply(struct stream
*s
, struct parameter
**p
,
498 e2
= evalue_read_factor(s
, p
);
500 stream_error(s
, NULL
, "unexpected EOF");
501 evalue_free(product
);
509 static evalue
*evalue_read_factor(struct stream
*s
, struct parameter
**p
)
514 tok
= stream_next_token(s
);
518 if (tok
->type
== '(') {
520 e
= evalue_read_term(s
, p
, 1);
521 tok
= stream_next_token(s
);
522 if (!tok
|| tok
->type
!= ')') {
523 stream_error(s
, tok
, "expecting \")\"");
525 stream_push_token(s
, tok
);
528 } else if (tok
->type
== TOKEN_VALUE
) {
529 int line
= tok
->line
;
532 value_set_si(e
->d
, 1);
534 value_assign(e
->x
.n
, tok
->u
.v
);
536 tok
= stream_next_token(s
);
537 if (tok
&& tok
->type
== '/') {
539 tok
= stream_next_token(s
);
540 if (!tok
|| tok
->type
!= TOKEN_VALUE
) {
541 stream_error(s
, tok
, "expecting denominator");
543 stream_push_token(s
, tok
);
546 value_assign(e
->d
, tok
->u
.v
);
548 } else if (tok
&& tok
->type
== TOKEN_IDENT
&& tok
->line
== line
) {
549 stream_push_token(s
, tok
);
550 e
= read_factor_and_multiply(s
, p
, e
);
552 stream_push_token(s
, tok
);
553 } else if (tok
->type
== TOKEN_IDENT
) {
554 int pos
= parameter_pos(p
, tok
->u
.s
, -1);
555 int pow
= optional_power(s
);
559 e
->x
.p
= new_enode(polynomial
, pow
+1, pos
+1);
560 evalue_set_si(&e
->x
.p
->arr
[pow
], 1, 1);
562 evalue_set_si(&e
->x
.p
->arr
[pow
], 0, 1);
563 } else if (tok
->type
== '[') {
564 stream_push_token(s
, tok
);
565 e
= read_periodic(s
, p
);
566 } else if (tok
->type
== '{') {
567 stream_push_token(s
, tok
);
568 e
= read_fract(s
, tok
, p
);
571 tok
= stream_next_token(s
);
572 if (tok
&& tok
->type
== '*') {
574 e
= read_factor_and_multiply(s
, p
, e
);
576 stream_push_token(s
, tok
);
581 static evalue
*evalue_read_term(struct stream
*s
, struct parameter
**p
,
587 e
= evalue_read_factor(s
, p
);
591 tok
= stream_next_token(s
);
595 if (!multi_line
&& tok
->on_new_line
)
596 stream_push_token(s
, tok
);
597 else if (tok
->type
== '+' || tok
->type
== TOKEN_VALUE
) {
599 if (tok
->type
== '+')
602 stream_push_token(s
, tok
);
603 e2
= evalue_read_term(s
, p
, multi_line
);
605 stream_error(s
, NULL
, "unexpected EOF");
611 stream_push_token(s
, tok
);
619 struct constraint
*next
;
620 struct constraint
*union_next
;
623 static struct constraint
*constraint_new()
625 struct constraint
*c
= ALLOC(struct constraint
);
627 c
->v
= Vector_Alloc(16);
629 c
->union_next
= NULL
;
633 static void constraint_free(struct constraint
*c
)
636 struct constraint
*next
= c
->next
? c
->next
: c
->union_next
;
643 static void constraint_extend(struct constraint
*c
, int pos
)
646 if (pos
< c
->v
->Size
)
649 v
= Vector_Alloc((3*c
->v
->Size
)/2);
650 Vector_Copy(c
->v
->p
, v
->p
, c
->v
->Size
);
655 static int evalue_read_constraint(struct stream
*s
, struct parameter
**p
,
656 struct constraint
**constraints
,
657 struct constraint
*union_next
)
660 struct constraint
*c
= NULL
;
662 while ((tok
= stream_next_token(s
))) {
665 if (tok
->type
== '+')
667 else if (tok
->type
== TOKEN_IDENT
) {
669 c
= constraint_new();
670 pos
= parameter_pos(p
, tok
->u
.s
, -1);
671 constraint_extend(c
, 1+pos
);
672 value_set_si(c
->v
->p
[1+pos
], 1);
674 } else if (tok
->type
== TOKEN_VALUE
) {
676 c
= constraint_new();
677 tok2
= stream_next_token(s
);
678 if (tok2
&& tok2
->type
== TOKEN_VALUE
) {
679 /* Handle "-" space cst, where "-" is translated to -1 */
680 value_multiply(tok
->u
.v
, tok
->u
.v
, tok2
->u
.v
);
682 tok2
= stream_next_token(s
);
684 if (tok2
&& tok2
->type
== TOKEN_IDENT
) {
685 pos
= parameter_pos(p
, tok2
->u
.s
, -1);
686 constraint_extend(c
, 1+pos
);
687 value_assign(c
->v
->p
[1+pos
], tok
->u
.v
);
692 stream_push_token(s
, tok2
);
693 value_assign(c
->v
->p
[0], tok
->u
.v
);
696 } else if (tok
->type
== TOKEN_GE
|| tok
->type
== '=') {
697 int type
= tok
->type
== TOKEN_GE
;
699 tok
= stream_next_token(s
);
700 if (!tok
|| tok
->type
!= TOKEN_VALUE
|| value_notzero_p(tok
->u
.v
)) {
701 stream_error(s
, tok
, "expecting \"0\"");
703 stream_push_token(s
, tok
);
707 stream_error(s
, NULL
, "empty constraint");
711 c
->next
= *constraints
;
712 c
->union_next
= union_next
;
720 stream_push_token(s
, tok
);
722 stream_error(s
, tok
, "unexpected token");
731 static struct constraint
*evalue_read_domain(struct stream
*s
, struct parameter
**p
,
734 struct constraint
*constraints
= NULL
;
735 struct constraint
*union_next
= NULL
;
739 tok
= stream_next_token(s
);
742 stream_push_token(s
, tok
);
745 while (evalue_read_constraint(s
, p
, &constraints
, union_next
)) {
746 tok
= stream_next_token(s
);
748 if (tok
->type
== TOKEN_UNION
) {
750 tok
= stream_next_token(s
);
752 stream_error(s
, NULL
, "unexpected EOF");
755 stream_push_token(s
, tok
);
756 union_next
= constraints
;
760 stream_push_token(s
, tok
);
761 /* empty line separates domain from evalue */
762 if (tok
->line
> line
+1)
772 struct constraint
*constraints
;
774 struct section
*next
;
777 static const char **extract_parameters(struct parameter
*p
, unsigned *nparam
)
782 *nparam
= p
? p
->pos
+1 : 0;
783 params
= ALLOCN(const char *, *nparam
);
784 for (i
= 0; i
< *nparam
; ++i
) {
785 struct parameter
*next
= p
->next
;
786 params
[p
->pos
] = p
->name
;
793 static Polyhedron
*constraints2domain(struct constraint
*constraints
,
794 unsigned nparam
, unsigned MaxRays
)
799 struct constraint
*c
;
800 struct constraint
*union_next
= NULL
;
802 for (n
= 0, c
= constraints
; c
; ++n
, c
= c
->next
)
804 M
= Matrix_Alloc(n
, 1+nparam
+1);
806 struct constraint
*next
= constraints
->next
;
807 union_next
= constraints
->union_next
;
808 Vector_Copy(constraints
->v
->p
+1, M
->p
[n
]+1, nparam
);
809 if (constraints
->type
)
810 value_set_si(M
->p
[n
][0], 1);
811 value_assign(M
->p
[n
][1+nparam
], constraints
->v
->p
[0]);
812 constraints
->next
= NULL
;
813 constraints
->union_next
= NULL
;
814 constraint_free(constraints
);
817 D
= Constraints2Polyhedron(M
, MaxRays
);
821 D
= DomainConcat(D
, constraints2domain(union_next
, nparam
, MaxRays
));
825 static evalue
*evalue_read_partition(struct stream
*s
, struct parameter
*p
,
827 unsigned *nparam
, unsigned MaxRays
)
829 struct section
*part
= NULL
;
830 struct constraint
*constraints
;
834 while ((constraints
= evalue_read_domain(s
, &p
, MaxRays
))) {
835 struct section
*sect
;
836 evalue
*e
= evalue_read_term(s
, &p
, 0);
838 stream_error(s
, NULL
, "missing evalue");
841 sect
= ALLOC(struct section
);
842 sect
->constraints
= constraints
;
853 *ppp
= extract_parameters(p
, nparam
);
856 e
->x
.p
= new_enode(partition
, 2*m
, *nparam
);
858 for (j
= 0; j
< m
; ++j
) {
860 struct section
*next
= part
->next
;
861 constraints
= part
->constraints
;
862 D
= constraints2domain(part
->constraints
, *nparam
, MaxRays
);
863 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[2*(m
-j
-1)], D
);
864 value_clear(e
->x
.p
->arr
[2*(m
-j
-1)+1].d
);
865 e
->x
.p
->arr
[2*(m
-j
-1)+1] = *part
->e
;
874 static evalue
*evalue_read(struct stream
*s
, const char *var_list
,
876 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
880 struct parameter
*p
= NULL
;
885 while ((next
= strchr(var_list
, ','))) {
887 parameter_pos(&p
, var_list
, next
-var_list
);
890 if (strlen(var_list
) > 0)
891 parameter_pos(&p
, var_list
, -1);
892 nv
= p
? p
->pos
+1 : 0;
896 if (!(tok
= stream_next_token(s
)))
899 if (tok
->type
== TOKEN_VARS
) {
902 tok
= stream_next_token(s
);
903 if (!tok
|| tok
->type
!= TOKEN_IDENT
) {
904 stream_error(s
, tok
, "expecting identifier");
908 parameter_pos(&p
, tok
->u
.s
, -1);
910 tok
= stream_next_token(s
);
911 if (!tok
|| tok
->type
!= ',')
918 nv
= p
? p
->pos
+1 : 0;
921 if (tok
->type
== '(' || tok
->type
== '[') {
922 stream_push_token(s
, tok
);
923 e
= evalue_read_term(s
, &p
, 0);
924 *ppp
= extract_parameters(p
, nparam
);
925 } else if (tok
->type
== TOKEN_VALUE
) {
926 struct token
*tok2
= stream_next_token(s
);
928 stream_push_token(s
, tok2
);
929 stream_push_token(s
, tok
);
930 if (tok2
&& (tok2
->type
== TOKEN_IDENT
|| tok2
->type
== TOKEN_GE
))
931 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
933 e
= evalue_read_term(s
, &p
, 0);
934 *ppp
= extract_parameters(p
, nparam
);
936 } else if (tok
->type
== TOKEN_IDENT
) {
937 stream_push_token(s
, tok
);
938 e
= evalue_read_partition(s
, p
, ppp
, nparam
, MaxRays
);
940 stream_error(s
, tok
, "unexpected token");
941 *nparam
= nv
== -1 ? 0 : nv
;
952 evalue
*evalue_read_from_file(FILE *in
, const char *var_list
,
954 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
957 struct stream
*s
= stream_new_file(in
);
958 e
= evalue_read(s
, var_list
, ppp
, nvar
, nparam
, MaxRays
);
963 evalue
*evalue_read_from_str(const char *str
, const char *var_list
,
965 unsigned *nvar
, unsigned *nparam
, unsigned MaxRays
)
968 struct stream
*s
= stream_new_str(str
);
969 e
= evalue_read(s
, var_list
, ppp
, nvar
, nparam
, MaxRays
);