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"
18 enum isl_token_type type
;
21 static int same_name(const void *entry
, const void *val
)
23 const struct isl_keyword
*keyword
= (const struct isl_keyword
*)entry
;
25 return !strcmp(keyword
->name
, val
);
28 enum isl_token_type
isl_stream_register_keyword(struct isl_stream
*s
,
31 struct isl_hash_table_entry
*entry
;
32 struct isl_keyword
*keyword
;
36 s
->keywords
= isl_hash_table_alloc(s
->ctx
, 10);
38 return ISL_TOKEN_ERROR
;
39 s
->next_type
= ISL_TOKEN_LAST
;
42 name_hash
= isl_hash_string(isl_hash_init(), name
);
44 entry
= isl_hash_table_find(s
->ctx
, s
->keywords
, name_hash
,
47 return ISL_TOKEN_ERROR
;
49 keyword
= entry
->data
;
53 keyword
= isl_calloc_type(s
->ctx
, struct isl_keyword
);
55 return ISL_TOKEN_ERROR
;
56 keyword
->type
= s
->next_type
++;
57 keyword
->name
= strdup(name
);
60 return ISL_TOKEN_ERROR
;
62 entry
->data
= keyword
;
67 static struct isl_token
*isl_token_new(struct isl_ctx
*ctx
,
68 int line
, int col
, unsigned on_new_line
)
70 struct isl_token
*tok
= isl_alloc_type(ctx
, struct isl_token
);
75 tok
->on_new_line
= on_new_line
;
79 void isl_token_free(struct isl_token
*tok
)
83 if (tok
->type
== ISL_TOKEN_VALUE
)
84 isl_int_clear(tok
->u
.v
);
85 else if (tok
->type
== ISL_TOKEN_IDENT
)
90 void isl_stream_error(struct isl_stream
*s
, struct isl_token
*tok
, char *msg
)
92 int line
= tok
? tok
->line
: s
->line
;
93 int col
= tok
? tok
->col
: s
->col
;
94 fprintf(stderr
, "syntax error (%d, %d): %s\n", line
, col
, msg
);
97 fprintf(stderr
, "got '%c'\n", tok
->type
);
99 fprintf(stderr
, "got token type %d\n", tok
->type
);
103 static struct isl_stream
* isl_stream_new(struct isl_ctx
*ctx
)
106 struct isl_stream
*s
= isl_alloc_type(ctx
, struct isl_stream
);
114 s
->buffer
= isl_alloc_array(ctx
, char, s
->size
);
122 for (i
= 0; i
< 5; ++i
)
132 struct isl_stream
* isl_stream_new_file(struct isl_ctx
*ctx
, FILE *file
)
134 struct isl_stream
*s
= isl_stream_new(ctx
);
141 struct isl_stream
* isl_stream_new_str(struct isl_ctx
*ctx
, const char *str
)
143 struct isl_stream
*s
= isl_stream_new(ctx
);
148 static int isl_stream_getc(struct isl_stream
*s
)
173 static void isl_stream_ungetc(struct isl_stream
*s
, int c
)
182 static int isl_stream_push_char(struct isl_stream
*s
, int c
)
184 if (s
->len
>= s
->size
) {
185 s
->size
= (3*s
->size
)/2;
186 s
->buffer
= isl_realloc_array(ctx
, s
->buffer
, char, s
->size
);
190 s
->buffer
[s
->len
++] = c
;
194 void isl_stream_push_token(struct isl_stream
*s
, struct isl_token
*tok
)
196 isl_assert(s
->ctx
, s
->n_token
< 5, return);
197 s
->tokens
[s
->n_token
++] = tok
;
200 static enum isl_token_type
check_keywords(struct isl_stream
*s
)
202 struct isl_hash_table_entry
*entry
;
203 struct isl_keyword
*keyword
;
206 if (!strcasecmp(s
->buffer
, "exists"))
207 return ISL_TOKEN_EXISTS
;
208 if (!strcasecmp(s
->buffer
, "and"))
209 return ISL_TOKEN_AND
;
210 if (!strcasecmp(s
->buffer
, "or"))
212 if (!strcasecmp(s
->buffer
, "infty"))
213 return ISL_TOKEN_INFTY
;
214 if (!strcasecmp(s
->buffer
, "infinity"))
215 return ISL_TOKEN_INFTY
;
216 if (!strcasecmp(s
->buffer
, "NaN"))
217 return ISL_TOKEN_NAN
;
220 return ISL_TOKEN_IDENT
;
222 name_hash
= isl_hash_string(isl_hash_init(), s
->buffer
);
223 entry
= isl_hash_table_find(s
->ctx
, s
->keywords
, name_hash
, same_name
,
226 keyword
= entry
->data
;
227 return keyword
->type
;
230 return ISL_TOKEN_IDENT
;
233 static struct isl_token
*next_token(struct isl_stream
*s
, int same_line
)
236 struct isl_token
*tok
= NULL
;
238 int old_line
= s
->line
;
241 if (same_line
&& s
->tokens
[s
->n_token
- 1]->on_new_line
)
243 return s
->tokens
[--s
->n_token
];
246 if (same_line
&& s
->c
== '\n')
251 /* skip spaces and comment lines */
252 while ((c
= isl_stream_getc(s
)) != -1) {
254 while ((c
= isl_stream_getc(s
)) != -1 && c
!= '\n')
257 if (c
== -1 || (same_line
&& c
== '\n'))
259 } else if (!isspace(c
) || (same_line
&& c
== '\n'))
266 if (c
== -1 || (same_line
&& c
== '\n'))
281 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
284 tok
->type
= (enum isl_token_type
)c
;
289 if ((c
= isl_stream_getc(s
)) == '>') {
290 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
293 tok
->type
= ISL_TOKEN_TO
;
297 isl_stream_ungetc(s
, c
);
299 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
302 tok
->type
= (enum isl_token_type
) '-';
306 if (c
== '-' || isdigit(c
)) {
307 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
310 tok
->type
= ISL_TOKEN_VALUE
;
311 isl_int_init(tok
->u
.v
);
312 if (isl_stream_push_char(s
, c
))
314 while ((c
= isl_stream_getc(s
)) != -1 && isdigit(c
))
315 if (isl_stream_push_char(s
, c
))
318 isl_stream_ungetc(s
, c
);
319 isl_stream_push_char(s
, '\0');
320 isl_int_read(tok
->u
.v
, s
->buffer
);
324 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
327 isl_stream_push_char(s
, c
);
328 while ((c
= isl_stream_getc(s
)) != -1 && isalnum(c
))
329 isl_stream_push_char(s
, c
);
331 isl_stream_ungetc(s
, c
);
332 while ((c
= isl_stream_getc(s
)) != -1 && c
== '\'')
333 isl_stream_push_char(s
, c
);
335 isl_stream_ungetc(s
, c
);
336 isl_stream_push_char(s
, '\0');
337 tok
->type
= check_keywords(s
);
338 if (tok
->type
== ISL_TOKEN_IDENT
)
339 tok
->u
.s
= strdup(s
->buffer
);
344 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
347 if ((c
= isl_stream_getc(s
)) == '=') {
348 tok
->type
= ISL_TOKEN_DEF
;
352 isl_stream_ungetc(s
, c
);
358 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
361 if ((c
= isl_stream_getc(s
)) == '=') {
362 tok
->type
= ISL_TOKEN_GE
;
366 isl_stream_ungetc(s
, c
);
367 tok
->type
= ISL_TOKEN_GT
;
372 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
375 if ((c
= isl_stream_getc(s
)) == '=') {
376 tok
->type
= ISL_TOKEN_LE
;
380 isl_stream_ungetc(s
, c
);
381 tok
->type
= ISL_TOKEN_LT
;
385 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
388 tok
->type
= ISL_TOKEN_AND
;
389 if ((c
= isl_stream_getc(s
)) != '&' && c
!= -1)
390 isl_stream_ungetc(s
, c
);
394 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
397 tok
->type
= ISL_TOKEN_OR
;
398 if ((c
= isl_stream_getc(s
)) != '|' && c
!= -1)
399 isl_stream_ungetc(s
, c
);
403 tok
= isl_token_new(s
->ctx
, line
, col
, old_line
!= line
);
406 tok
->type
= ISL_TOKEN_UNKNOWN
;
413 struct isl_token
*isl_stream_next_token(struct isl_stream
*s
)
415 return next_token(s
, 0);
418 struct isl_token
*isl_stream_next_token_on_same_line(struct isl_stream
*s
)
420 return next_token(s
, 1);
423 int isl_stream_eat_if_available(struct isl_stream
*s
, int type
)
425 struct isl_token
*tok
;
427 tok
= isl_stream_next_token(s
);
430 if (tok
->type
== type
) {
434 isl_stream_push_token(s
, tok
);
438 int isl_stream_next_token_is(struct isl_stream
*s
, int type
)
440 struct isl_token
*tok
;
443 tok
= isl_stream_next_token(s
);
446 r
= tok
->type
== type
;
447 isl_stream_push_token(s
, tok
);
451 char *isl_stream_read_ident_if_available(struct isl_stream
*s
)
453 struct isl_token
*tok
;
455 tok
= isl_stream_next_token(s
);
458 if (tok
->type
== ISL_TOKEN_IDENT
) {
459 char *ident
= strdup(tok
->u
.s
);
463 isl_stream_push_token(s
, tok
);
467 int isl_stream_eat(struct isl_stream
*s
, int type
)
469 struct isl_token
*tok
;
471 tok
= isl_stream_next_token(s
);
474 if (tok
->type
== type
) {
478 isl_stream_error(s
, tok
, "expecting other token");
479 isl_stream_push_token(s
, tok
);
483 int isl_stream_is_empty(struct isl_stream
*s
)
485 struct isl_token
*tok
;
487 tok
= isl_stream_next_token(s
);
492 isl_stream_push_token(s
, tok
);
496 static int free_keyword(void *p
)
498 struct isl_keyword
*keyword
= p
;
506 void isl_stream_free(struct isl_stream
*s
)
511 if (s
->n_token
!= 0) {
512 struct isl_token
*tok
= isl_stream_next_token(s
);
513 isl_stream_error(s
, tok
, "unexpected token");
517 isl_hash_table_foreach(s
->ctx
, s
->keywords
, free_keyword
);
518 isl_hash_table_free(s
->ctx
, s
->keywords
);
520 isl_ctx_deref(s
->ctx
);