2 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
14 #include "isl_stream.h"
16 static struct isl_token
*isl_token_new(struct isl_ctx
*ctx
,
17 int line
, int col
, unsigned on_new_line
)
19 struct isl_token
*tok
= isl_alloc_type(ctx
, struct isl_token
);
24 tok
->on_new_line
= on_new_line
;
28 void isl_token_free(struct isl_token
*tok
)
32 if (tok
->type
== ISL_TOKEN_VALUE
)
33 isl_int_clear(tok
->u
.v
);
34 else if (tok
->type
== ISL_TOKEN_IDENT
)
39 void isl_stream_error(struct isl_stream
*s
, struct isl_token
*tok
, char *msg
)
41 int line
= tok
? tok
->line
: s
->line
;
42 int col
= tok
? tok
->col
: s
->col
;
43 fprintf(stderr
, "syntax error (%d, %d): %s\n", line
, col
, msg
);
46 fprintf(stderr
, "got '%c'\n", tok
->type
);
48 fprintf(stderr
, "got token type %d\n", tok
->type
);
52 static struct isl_stream
* isl_stream_new(struct isl_ctx
*ctx
)
55 struct isl_stream
*s
= isl_alloc_type(ctx
, struct isl_stream
);
63 s
->buffer
= isl_alloc_array(ctx
, char, s
->size
);
71 for (i
= 0; i
< 5; ++i
)
80 struct isl_stream
* isl_stream_new_file(struct isl_ctx
*ctx
, FILE *file
)
82 struct isl_stream
*s
= isl_stream_new(ctx
);
89 struct isl_stream
* isl_stream_new_str(struct isl_ctx
*ctx
, const char *str
)
91 struct isl_stream
*s
= isl_stream_new(ctx
);
96 static int isl_stream_getc(struct isl_stream
*s
)
121 static void isl_stream_ungetc(struct isl_stream
*s
, int c
)
130 static int isl_stream_push_char(struct isl_stream
*s
, int c
)
132 if (s
->len
>= s
->size
) {
133 s
->size
= (3*s
->size
)/2;
134 s
->buffer
= isl_realloc_array(ctx
, s
->buffer
, char, s
->size
);
138 s
->buffer
[s
->len
++] = c
;
142 void isl_stream_push_token(struct isl_stream
*s
, struct isl_token
*tok
)
144 isl_assert(s
->ctx
, s
->n_token
< 5, return);
145 s
->tokens
[s
->n_token
++] = tok
;
148 static struct isl_token
*next_token(struct isl_stream
*s
, int same_line
)
151 struct isl_token
*tok
= NULL
;
153 int old_line
= s
->line
;
156 if (same_line
&& s
->tokens
[s
->n_token
- 1]->on_new_line
)
158 return s
->tokens
[--s
->n_token
];
161 if (same_line
&& s
->c
== '\n')
166 /* skip spaces and comment lines */
167 while ((c
= isl_stream_getc(s
)) != -1) {
169 while ((c
= isl_stream_getc(s
)) != -1 && c
!= '\n')
172 if (c
== -1 || (same_line
&& c
== '\n'))
174 } else if (!isspace(c
) || (same_line
&& c
== '\n'))
181 if (c
== -1 || (same_line
&& c
== '\n'))
196 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
199 tok
->type
= (enum isl_token_type
)c
;
204 if ((c
= isl_stream_getc(s
)) == '>') {
205 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
208 tok
->type
= ISL_TOKEN_TO
;
212 isl_stream_ungetc(s
, c
);
214 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
217 tok
->type
= (enum isl_token_type
) '-';
221 if (c
== '-' || isdigit(c
)) {
222 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
225 tok
->type
= ISL_TOKEN_VALUE
;
226 isl_int_init(tok
->u
.v
);
227 if (isl_stream_push_char(s
, c
))
229 while ((c
= isl_stream_getc(s
)) != -1 && isdigit(c
))
230 if (isl_stream_push_char(s
, c
))
233 isl_stream_ungetc(s
, c
);
234 isl_stream_push_char(s
, '\0');
235 isl_int_read(tok
->u
.v
, s
->buffer
);
239 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
242 isl_stream_push_char(s
, c
);
243 while ((c
= isl_stream_getc(s
)) != -1 && isalnum(c
))
244 isl_stream_push_char(s
, c
);
246 isl_stream_ungetc(s
, c
);
247 while ((c
= isl_stream_getc(s
)) != -1 && c
== '\'')
248 isl_stream_push_char(s
, c
);
250 isl_stream_ungetc(s
, c
);
251 isl_stream_push_char(s
, '\0');
252 if (!strcasecmp(s
->buffer
, "exists"))
253 tok
->type
= ISL_TOKEN_EXISTS
;
254 else if (!strcasecmp(s
->buffer
, "and"))
255 tok
->type
= ISL_TOKEN_AND
;
256 else if (!strcasecmp(s
->buffer
, "or"))
257 tok
->type
= ISL_TOKEN_OR
;
259 tok
->type
= ISL_TOKEN_IDENT
;
260 tok
->u
.s
= strdup(s
->buffer
);
266 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
269 if ((c
= isl_stream_getc(s
)) == '=') {
270 tok
->type
= ISL_TOKEN_DEF
;
274 isl_stream_ungetc(s
, c
);
280 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
283 if ((c
= isl_stream_getc(s
)) == '=') {
284 tok
->type
= ISL_TOKEN_GE
;
288 isl_stream_ungetc(s
, c
);
289 tok
->type
= ISL_TOKEN_GT
;
294 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
297 if ((c
= isl_stream_getc(s
)) == '=') {
298 tok
->type
= ISL_TOKEN_LE
;
302 isl_stream_ungetc(s
, c
);
303 tok
->type
= ISL_TOKEN_LT
;
307 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
310 tok
->type
= ISL_TOKEN_AND
;
311 if ((c
= isl_stream_getc(s
)) != '&' && c
!= -1)
312 isl_stream_ungetc(s
, c
);
316 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
319 tok
->type
= ISL_TOKEN_OR
;
320 if ((c
= isl_stream_getc(s
)) != '|' && c
!= -1)
321 isl_stream_ungetc(s
, c
);
325 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
328 tok
->type
= ISL_TOKEN_UNKNOWN
;
335 struct isl_token
*isl_stream_next_token(struct isl_stream
*s
)
337 return next_token(s
, 0);
340 struct isl_token
*isl_stream_next_token_on_same_line(struct isl_stream
*s
)
342 return next_token(s
, 1);
345 int isl_stream_eat(struct isl_stream
*s
, int type
)
347 struct isl_token
*tok
;
349 tok
= isl_stream_next_token(s
);
352 if (tok
->type
== type
) {
356 isl_stream_error(s
, tok
, "expecting other token");
357 isl_stream_push_token(s
, tok
);
361 void isl_stream_free(struct isl_stream
*s
)
366 if (s
->n_token
!= 0) {
367 struct isl_token
*tok
= isl_stream_next_token(s
);
368 isl_stream_error(s
, tok
, "unexpected token");
371 isl_ctx_deref(s
->ctx
);