5 #include "symbol_table_t.h"
7 #include "adt/strset.h"
21 /* No strtold on windows and no replacement yet */
22 #define strtold(s, e) strtod(s, e)
29 static char buf[1024 + MAX_PUTBACK];
30 static const char *bufend;
31 static const char *bufpos;
32 static strset_t stringset;
34 static type_t *type_int = NULL;
35 static type_t *type_uint = NULL;
36 static type_t *type_long = NULL;
37 static type_t *type_ulong = NULL;
38 static type_t *type_longlong = NULL;
39 static type_t *type_ulonglong = NULL;
40 static type_t *type_float = NULL;
41 static type_t *type_double = NULL;
42 static type_t *type_longdouble = NULL;
44 static void error_prefix_at(const char *input_name, unsigned linenr)
46 fprintf(stderr, "%s:%u: Error: ", input_name, linenr);
49 static void error_prefix(void)
51 error_prefix_at(lexer_token.source_position.input_name,
52 lexer_token.source_position.linenr);
55 static void parse_error(const char *msg)
58 fprintf(stderr, "%s\n", msg);
61 static inline void next_real_char(void)
64 if(bufpos >= bufend) {
65 size_t s = fread(buf + MAX_PUTBACK, 1, sizeof(buf) - MAX_PUTBACK,
71 bufpos = buf + MAX_PUTBACK;
72 bufend = buf + MAX_PUTBACK + s;
77 static inline void put_back(int pc)
79 assert(bufpos >= buf);
80 //assert(bufpos < buf+MAX_PUTBACK || *bufpos == pc);
82 char *p = buf + (bufpos - buf);
85 /* going backwards in the buffer is legal as long as it's not more often
90 printf("putback '%c'\n", pc);
94 static inline void next_char(void);
96 #define MATCH_NEWLINE(code) \
102 lexer_token.source_position.linenr++; \
106 lexer_token.source_position.linenr++; \
109 #define eat(c_type) do { assert(c == c_type); next_char(); } while(0)
111 static void maybe_concat_lines(void)
116 MATCH_NEWLINE(return;)
126 static inline void next_char(void)
130 /* filter trigraphs */
131 if(UNLIKELY(c == '\\')) {
132 maybe_concat_lines();
133 goto end_of_next_char;
137 goto end_of_next_char;
140 if(LIKELY(c != '?')) {
143 goto end_of_next_char;
148 case '=': c = '#'; break;
149 case '(': c = '['; break;
150 case '/': c = '\\'; maybe_concat_lines(); break;
151 case ')': c = ']'; break;
152 case '\'': c = '^'; break;
153 case '<': c = '{'; break;
154 case '!': c = '|'; break;
155 case '>': c = '}'; break;
156 case '-': c = '~'; break;
166 printf("nchar '%c'\n", c);
170 #define SYMBOL_CHARS \
237 static void parse_symbol(void)
242 obstack_1grow(&symbol_obstack, c);
249 obstack_1grow(&symbol_obstack, c);
259 obstack_1grow(&symbol_obstack, '\0');
261 string = obstack_finish(&symbol_obstack);
262 symbol = symbol_table_insert(string);
264 lexer_token.type = symbol->ID;
265 lexer_token.v.symbol = symbol;
267 if(symbol->string != string) {
268 obstack_free(&symbol_obstack, string);
272 static void parse_integer_suffix(void)
274 if(c == 'U' || c == 'u') {
276 if(c == 'L' || c == 'l') {
278 if(c == 'L' || c == 'l') {
280 lexer_token.datatype = type_ulonglong;
282 lexer_token.datatype = type_ulong;
285 lexer_token.datatype = type_uint;
287 } else if(c == 'l' || c == 'L') {
289 if(c == 'l' || c == 'L') {
291 if(c == 'u' || c == 'U') {
293 lexer_token.datatype = type_ulonglong;
295 lexer_token.datatype = type_longlong;
297 } else if(c == 'u' || c == 'U') {
299 lexer_token.datatype = type_ulong;
301 lexer_token.datatype = type_int;
304 lexer_token.datatype = type_int;
308 static void parse_floating_suffix(void)
311 /* TODO: do something usefull with the suffixes... */
315 lexer_token.datatype = type_float;
320 lexer_token.datatype = type_longdouble;
323 lexer_token.datatype = type_double;
329 * A replacement for strtoull. Only those parts needed for
330 * our parser are implemented.
332 static unsigned long long parse_int_string(const char *s, const char **endptr, int base) {
333 unsigned long long v = 0;
338 /* check for overrun */
339 if (v <= 0x1000000000000000ULL)
341 switch (tolower(*s)) {
342 case '0': v <<= 4; break;
343 case '1': v <<= 4; v |= 0x1; break;
344 case '2': v <<= 4; v |= 0x2; break;
345 case '3': v <<= 4; v |= 0x3; break;
346 case '4': v <<= 4; v |= 0x4; break;
347 case '5': v <<= 4; v |= 0x5; break;
348 case '6': v <<= 4; v |= 0x6; break;
349 case '7': v <<= 4; v |= 0x7; break;
350 case '8': v <<= 4; v |= 0x8; break;
351 case '9': v <<= 4; v |= 0x9; break;
352 case 'a': v <<= 4; v |= 0xa; break;
353 case 'b': v <<= 4; v |= 0xb; break;
354 case 'c': v <<= 4; v |= 0xc; break;
355 case 'd': v <<= 4; v |= 0xd; break;
356 case 'e': v <<= 4; v |= 0xe; break;
357 case 'f': v <<= 4; v |= 0xf; break;
365 /* check for overrun */
366 if (v <= 0x2000000000000000ULL)
368 switch (tolower(*s)) {
369 case '0': v <<= 3; break;
370 case '1': v <<= 3; v |= 1; break;
371 case '2': v <<= 3; v |= 2; break;
372 case '3': v <<= 3; v |= 3; break;
373 case '4': v <<= 3; v |= 4; break;
374 case '5': v <<= 3; v |= 5; break;
375 case '6': v <<= 3; v |= 6; break;
376 case '7': v <<= 3; v |= 7; break;
384 /* check for overrun */
385 if (v > 0x1999999999999999ULL)
387 switch (tolower(*s)) {
388 case '0': v *= 10; break;
389 case '1': v *= 10; v += 1; break;
390 case '2': v *= 10; v += 2; break;
391 case '3': v *= 10; v += 3; break;
392 case '4': v *= 10; v += 4; break;
393 case '5': v *= 10; v += 5; break;
394 case '6': v *= 10; v += 6; break;
395 case '7': v *= 10; v += 7; break;
396 case '8': v *= 10; v += 8; break;
397 case '9': v *= 10; v += 9; break;
412 static void parse_number_hex(void)
414 assert(c == 'x' || c == 'X');
418 obstack_1grow(&symbol_obstack, c);
421 obstack_1grow(&symbol_obstack, '\0');
422 char *string = obstack_finish(&symbol_obstack);
424 if(c == '.' || c == 'p' || c == 'P') {
426 panic("Hex floating point numbers not implemented yet");
428 if(*string == '\0') {
429 parse_error("invalid hex number");
430 lexer_token.type = T_ERROR;
434 lexer_token.type = T_INTEGER;
435 lexer_token.v.intvalue = parse_int_string(string, &endptr, 16);
436 if(*endptr != '\0') {
437 parse_error("hex number literal too long");
440 obstack_free(&symbol_obstack, string);
441 parse_integer_suffix();
444 static inline bool is_octal_digit(int chr)
446 return '0' <= chr && chr <= '7';
449 static void parse_number_oct(void)
451 while(is_octal_digit(c)) {
452 obstack_1grow(&symbol_obstack, c);
455 obstack_1grow(&symbol_obstack, '\0');
456 char *string = obstack_finish(&symbol_obstack);
459 lexer_token.type = T_INTEGER;
460 lexer_token.v.intvalue = parse_int_string(string, &endptr, 8);
461 if(*endptr != '\0') {
462 parse_error("octal number literal too long");
465 obstack_free(&symbol_obstack, string);
466 parse_integer_suffix();
469 static void parse_number_dec(void)
471 bool is_float = false;
473 obstack_1grow(&symbol_obstack, c);
478 obstack_1grow(&symbol_obstack, '.');
482 obstack_1grow(&symbol_obstack, c);
487 if(c == 'e' || c == 'E') {
488 obstack_1grow(&symbol_obstack, 'e');
491 if(c == '-' || c == '+') {
492 obstack_1grow(&symbol_obstack, c);
497 obstack_1grow(&symbol_obstack, c);
503 obstack_1grow(&symbol_obstack, '\0');
504 char *string = obstack_finish(&symbol_obstack);
508 lexer_token.type = T_FLOATINGPOINT;
509 lexer_token.v.floatvalue = strtold(string, &endptr);
511 if(*endptr != '\0') {
512 parse_error("invalid number literal");
515 parse_floating_suffix();
517 lexer_token.type = T_INTEGER;
518 lexer_token.v.intvalue = parse_int_string(string, &endptr, 10);
520 if(*endptr != '\0') {
521 parse_error("invalid number literal");
524 parse_integer_suffix();
526 obstack_free(&symbol_obstack, string);
529 static void parse_number(void)
551 parse_error("invalid octal number");
552 lexer_token.type = T_ERROR;
558 obstack_1grow(&symbol_obstack, '0');
567 static int parse_octal_sequence(const int first_digit)
569 assert(is_octal_digit(first_digit));
570 int value = first_digit - '0';
571 if (!is_octal_digit(c)) return value;
572 value = 8 * value + c - '0';
574 if (!is_octal_digit(c)) return value;
575 value = 8 * value + c - '0';
580 static int parse_hex_sequence(void)
584 if (c >= '0' && c <= '9') {
585 value = 16 * value + c - '0';
586 } else if ('A' <= c && c <= 'F') {
587 value = 16 * value + c - 'A' + 10;
588 } else if ('a' <= c && c <= 'f') {
589 value = 16 * value + c - 'a' + 10;
599 static int parse_escape_sequence(void)
607 case '"': return '"';
608 case '\'': return '\'';
609 case '\\': return '\\';
610 case '?': return '\?';
611 case 'a': return '\a';
612 case 'b': return '\b';
613 case 'f': return '\f';
614 case 'n': return '\n';
615 case 'r': return '\r';
616 case 't': return '\t';
617 case 'v': return '\v';
619 return parse_hex_sequence();
628 return parse_octal_sequence(ec);
630 parse_error("reached end of file while parsing escape sequence");
633 parse_error("unknown escape sequence");
638 const char *concat_strings(const char *s1, const char *s2)
640 size_t len1 = strlen(s1);
641 size_t len2 = strlen(s2);
643 char *concat = obstack_alloc(&symbol_obstack, len1 + len2 + 1);
644 memcpy(concat, s1, len1);
645 memcpy(concat + len1, s2, len2 + 1);
647 const char *result = strset_insert(&stringset, concat);
648 if(result != concat) {
649 obstack_free(&symbol_obstack, concat);
655 static void parse_string_literal(void)
657 unsigned start_linenr = lexer_token.source_position.linenr;
668 tc = parse_escape_sequence();
669 obstack_1grow(&symbol_obstack, tc);
673 error_prefix_at(lexer_token.source_position.input_name,
675 fprintf(stderr, "string has no end\n");
676 lexer_token.type = T_ERROR;
684 obstack_1grow(&symbol_obstack, c);
692 /* TODO: concatenate multiple strings separated by whitespace... */
694 /* add finishing 0 to the string */
695 obstack_1grow(&symbol_obstack, '\0');
696 string = obstack_finish(&symbol_obstack);
698 /* check if there is already a copy of the string */
699 result = strset_insert(&stringset, string);
700 if(result != string) {
701 obstack_free(&symbol_obstack, string);
704 lexer_token.type = T_STRING_LITERAL;
705 lexer_token.v.string = result;
708 static void parse_character_constant(void)
716 found_char = parse_escape_sequence();
720 parse_error("newline while parsing character constant");
726 goto end_of_char_constant;
729 parse_error("EOF while parsing character constant");
730 lexer_token.type = T_ERROR;
734 if(found_char != 0) {
735 parse_error("more than 1 characters in character "
737 goto end_of_char_constant;
746 end_of_char_constant:
747 lexer_token.type = T_INTEGER;
748 lexer_token.v.intvalue = found_char;
751 static void skip_multiline_comment(void)
753 unsigned start_linenr = lexer_token.source_position.linenr;
765 MATCH_NEWLINE(break;)
768 error_prefix_at(lexer_token.source_position.input_name,
770 fprintf(stderr, "at end of file while looking for comment end\n");
780 static void skip_line_comment(void)
798 static token_t pp_token;
800 static inline void next_pp_token(void)
802 lexer_next_preprocessing_token();
803 pp_token = lexer_token;
806 static void eat_until_newline(void)
808 while(pp_token.type != '\n' && pp_token.type != T_EOF) {
813 static void error_directive(void)
816 fprintf(stderr, "#error directive: \n");
818 /* parse pp-tokens until new-line */
821 static void define_directive(void)
823 lexer_next_preprocessing_token();
824 if(lexer_token.type != T_IDENTIFIER) {
825 parse_error("expected identifier after #define\n");
830 static void ifdef_directive(int is_ifndef)
833 lexer_next_preprocessing_token();
834 //expect_identifier();
838 static void endif_directive(void)
843 static void parse_line_directive(void)
845 if(pp_token.type != T_INTEGER) {
846 parse_error("expected integer");
848 lexer_token.source_position.linenr = (unsigned int)(pp_token.v.intvalue - 1);
851 if(pp_token.type == T_STRING_LITERAL) {
852 lexer_token.source_position.input_name = pp_token.v.string;
859 static void parse_preprocessor_identifier(void)
861 assert(pp_token.type == T_IDENTIFIER);
862 symbol_t *symbol = pp_token.v.symbol;
864 switch(symbol->pp_ID) {
866 printf("include - enable header name parsing!\n");
882 parse_line_directive();
896 static void parse_preprocessor_directive(void)
900 switch(pp_token.type) {
902 parse_preprocessor_identifier();
905 parse_line_directive();
908 parse_error("invalid preprocessor directive");
914 #define MAYBE_PROLOG \
919 #define MAYBE(ch, set_type) \
922 lexer_token.type = set_type; \
925 #define ELSE_CODE(code) \
929 } /* end of while(1) */ \
932 #define ELSE(set_type) \
934 lexer_token.type = set_type; \
938 void lexer_next_preprocessing_token(void)
948 lexer_token.type = '\n';
954 /* might be a wide string ( L"string" ) */
955 if(c == '"' && (lexer_token.type == T_IDENTIFIER &&
956 lexer_token.v.symbol == symbol_L)) {
957 parse_string_literal();
967 parse_string_literal();
971 parse_character_constant();
978 MAYBE('.', T_DOTDOTDOT)
982 lexer_token.type = '.';
989 MAYBE('=', T_ANDEQUAL)
993 MAYBE('=', T_ASTERISKEQUAL)
997 MAYBE('+', T_PLUSPLUS)
998 MAYBE('=', T_PLUSEQUAL)
1002 MAYBE('>', T_MINUSGREATER)
1003 MAYBE('-', T_MINUSMINUS)
1004 MAYBE('=', T_MINUSEQUAL)
1008 MAYBE('=', T_EXCLAMATIONMARKEQUAL)
1012 MAYBE('=', T_SLASHEQUAL)
1015 skip_multiline_comment();
1016 lexer_next_preprocessing_token();
1020 skip_line_comment();
1021 lexer_next_preprocessing_token();
1026 MAYBE('>', T_PERCENTGREATER)
1027 MAYBE('=', T_PERCENTEQUAL)
1032 MAYBE(':', T_PERCENTCOLONPERCENTCOLON)
1036 lexer_token.type = T_PERCENTCOLON;
1039 ELSE(T_PERCENTCOLON)
1043 MAYBE(':', T_LESSCOLON)
1044 MAYBE('%', T_LESSPERCENT)
1045 MAYBE('=', T_LESSEQUAL)
1048 MAYBE('=', T_LESSLESSEQUAL)
1053 MAYBE('=', T_GREATEREQUAL)
1056 MAYBE('=', T_GREATERGREATEREQUAL)
1057 ELSE(T_GREATERGREATER)
1061 MAYBE('=', T_CARETEQUAL)
1065 MAYBE('=', T_PIPEEQUAL)
1066 MAYBE('|', T_PIPEPIPE)
1070 MAYBE('>', T_COLONGREATER)
1074 MAYBE('=', T_EQUALEQUAL)
1078 MAYBE('#', T_HASHHASH)
1092 lexer_token.type = c;
1097 lexer_token.type = T_EOF;
1103 fprintf(stderr, "unknown character '%c' found\n", c);
1104 lexer_token.type = T_ERROR;
1110 void lexer_next_token(void)
1112 lexer_next_preprocessing_token();
1113 if(lexer_token.type != '\n')
1118 lexer_next_preprocessing_token();
1119 } while(lexer_token.type == '\n');
1121 if(lexer_token.type == '#') {
1122 parse_preprocessor_directive();
1127 void init_lexer(void)
1129 strset_init(&stringset);
1131 type_int = make_atomic_type(ATOMIC_TYPE_INT, TYPE_QUALIFIER_CONST);
1132 type_uint = make_atomic_type(ATOMIC_TYPE_UINT, TYPE_QUALIFIER_CONST);
1133 type_long = make_atomic_type(ATOMIC_TYPE_LONG, TYPE_QUALIFIER_CONST);
1134 type_ulong = make_atomic_type(ATOMIC_TYPE_ULONG, TYPE_QUALIFIER_CONST);
1135 type_longlong = make_atomic_type(ATOMIC_TYPE_LONGLONG,
1136 TYPE_QUALIFIER_CONST);
1137 type_ulonglong = make_atomic_type(ATOMIC_TYPE_ULONGLONG,
1138 TYPE_QUALIFIER_CONST);
1140 type_float = make_atomic_type(ATOMIC_TYPE_FLOAT, TYPE_QUALIFIER_CONST);
1141 type_double = make_atomic_type(ATOMIC_TYPE_DOUBLE,
1142 TYPE_QUALIFIER_CONST);
1143 type_longdouble = make_atomic_type(ATOMIC_TYPE_LONG_DOUBLE,
1144 TYPE_QUALIFIER_CONST);
1147 void lexer_open_stream(FILE *stream, const char *input_name)
1150 lexer_token.source_position.linenr = 0;
1151 lexer_token.source_position.input_name = input_name;
1153 symbol_L = symbol_table_insert("L");
1155 /* place a virtual \n at the beginning so the lexer knows that we're
1156 * at the beginning of a line */
1160 void exit_lexer(void)
1162 strset_destroy(&stringset);
1165 static __attribute__((unused))
1166 void dbg_pos(const source_position_t source_position)
1168 fprintf(stdout, "%s:%d\n", source_position.input_name,
1169 source_position.linenr);