3 #include "diagnostic.h"
6 #include "symbol_table_t.h"
8 #include "adt/strset.h"
12 #include "target_architecture.h"
15 #include "lang_features.h"
27 /* No strtold on windows and no replacement yet */
28 #define strtold(s, e) strtod(s, e)
35 static char buf[1024 + MAX_PUTBACK];
36 static const char *bufend;
37 static const char *bufpos;
38 static strset_t stringset;
41 * Prints a parse error message at the current token.
43 * @param msg the error message
45 static void parse_error(const char *msg)
47 errorf(lexer_token.source_position, "%s", msg);
50 static inline void next_real_char(void)
52 assert(bufpos <= bufend);
53 if (bufpos >= bufend) {
54 size_t s = fread(buf + MAX_PUTBACK, 1, sizeof(buf) - MAX_PUTBACK,
60 bufpos = buf + MAX_PUTBACK;
61 bufend = buf + MAX_PUTBACK + s;
67 * Put a character back into the buffer.
69 * @param pc the character to put back
71 static inline void put_back(int pc)
74 *(--bufpos - buf + buf) = (char) pc;
77 printf("putback '%c'\n", pc);
81 static inline void next_char(void);
83 #define MATCH_NEWLINE(code) \
89 lexer_token.source_position.linenr++; \
93 lexer_token.source_position.linenr++; \
96 #define eat(c_type) do { assert(c == c_type); next_char(); } while(0)
98 static void maybe_concat_lines(void)
103 MATCH_NEWLINE(return;)
114 * Set c to the next input character, ie.
115 * after expanding trigraphs.
117 static inline void next_char(void)
121 /* filter trigraphs */
122 if(UNLIKELY(c == '\\')) {
123 maybe_concat_lines();
124 goto end_of_next_char;
128 goto end_of_next_char;
131 if(LIKELY(c != '?')) {
134 goto end_of_next_char;
139 case '=': c = '#'; break;
140 case '(': c = '['; break;
141 case '/': c = '\\'; maybe_concat_lines(); break;
142 case ')': c = ']'; break;
143 case '\'': c = '^'; break;
144 case '<': c = '{'; break;
145 case '!': c = '|'; break;
146 case '>': c = '}'; break;
147 case '-': c = '~'; break;
157 printf("nchar '%c'\n", c);
161 #define SYMBOL_CHARS \
229 * Read a symbol from the input and build
232 static void parse_symbol(void)
237 obstack_1grow(&symbol_obstack, (char) c);
244 obstack_1grow(&symbol_obstack, (char) c);
254 obstack_1grow(&symbol_obstack, '\0');
256 string = obstack_finish(&symbol_obstack);
257 symbol = symbol_table_insert(string);
259 lexer_token.type = symbol->ID;
260 lexer_token.v.symbol = symbol;
262 if(symbol->string != string) {
263 obstack_free(&symbol_obstack, string);
267 static void parse_integer_suffix(bool is_oct_hex)
269 bool is_unsigned = false;
270 bool min_long = false;
271 bool min_longlong = false;
273 if(c == 'U' || c == 'u') {
276 if(c == 'L' || c == 'l') {
279 if(c == 'L' || c == 'l') {
284 } else if(c == 'l' || c == 'L') {
287 if(c == 'l' || c == 'L') {
290 if(c == 'u' || c == 'U') {
294 } else if(c == 'u' || c == 'U') {
297 lexer_token.datatype = type_unsigned_long;
302 long long v = lexer_token.v.intvalue;
304 if(v >= TARGET_INT_MIN && v <= TARGET_INT_MAX) {
305 lexer_token.datatype = type_int;
307 } else if(is_oct_hex && v >= 0 && v <= TARGET_UINT_MAX) {
308 lexer_token.datatype = type_unsigned_int;
313 if(v >= TARGET_LONG_MIN && v <= TARGET_LONG_MAX) {
314 lexer_token.datatype = type_long;
316 } else if(is_oct_hex && v >= 0 && v <= TARGET_ULONG_MAX) {
317 lexer_token.datatype = type_unsigned_long;
321 unsigned long long uv = (unsigned long long) v;
322 if(is_oct_hex && uv > (unsigned long long) TARGET_LONGLONG_MAX) {
323 lexer_token.datatype = type_unsigned_long_long;
327 lexer_token.datatype = type_long_long;
329 unsigned long long v = (unsigned long long) lexer_token.v.intvalue;
330 if(!min_long && v <= TARGET_UINT_MAX) {
331 lexer_token.datatype = type_unsigned_int;
334 if(!min_longlong && v <= TARGET_ULONG_MAX) {
335 lexer_token.datatype = type_unsigned_long;
338 lexer_token.datatype = type_unsigned_long_long;
342 static void parse_floating_suffix(void)
345 /* TODO: do something useful with the suffixes... */
349 lexer_token.datatype = type_float;
354 lexer_token.datatype = type_long_double;
357 lexer_token.datatype = type_double;
363 * A replacement for strtoull. Only those parts needed for
364 * our parser are implemented.
366 static unsigned long long parse_int_string(const char *s, const char **endptr, int base) {
367 unsigned long long v = 0;
372 /* check for overrun */
373 if (v >= 0x1000000000000000ULL)
375 switch (tolower(*s)) {
376 case '0': v <<= 4; break;
377 case '1': v <<= 4; v |= 0x1; break;
378 case '2': v <<= 4; v |= 0x2; break;
379 case '3': v <<= 4; v |= 0x3; break;
380 case '4': v <<= 4; v |= 0x4; break;
381 case '5': v <<= 4; v |= 0x5; break;
382 case '6': v <<= 4; v |= 0x6; break;
383 case '7': v <<= 4; v |= 0x7; break;
384 case '8': v <<= 4; v |= 0x8; break;
385 case '9': v <<= 4; v |= 0x9; break;
386 case 'a': v <<= 4; v |= 0xa; break;
387 case 'b': v <<= 4; v |= 0xb; break;
388 case 'c': v <<= 4; v |= 0xc; break;
389 case 'd': v <<= 4; v |= 0xd; break;
390 case 'e': v <<= 4; v |= 0xe; break;
391 case 'f': v <<= 4; v |= 0xf; break;
399 /* check for overrun */
400 if (v >= 0x2000000000000000ULL)
402 switch (tolower(*s)) {
403 case '0': v <<= 3; break;
404 case '1': v <<= 3; v |= 1; break;
405 case '2': v <<= 3; v |= 2; break;
406 case '3': v <<= 3; v |= 3; break;
407 case '4': v <<= 3; v |= 4; break;
408 case '5': v <<= 3; v |= 5; break;
409 case '6': v <<= 3; v |= 6; break;
410 case '7': v <<= 3; v |= 7; break;
418 /* check for overrun */
419 if (v > 0x1999999999999999ULL)
421 switch (tolower(*s)) {
422 case '0': v *= 10; break;
423 case '1': v *= 10; v += 1; break;
424 case '2': v *= 10; v += 2; break;
425 case '3': v *= 10; v += 3; break;
426 case '4': v *= 10; v += 4; break;
427 case '5': v *= 10; v += 5; break;
428 case '6': v *= 10; v += 6; break;
429 case '7': v *= 10; v += 7; break;
430 case '8': v *= 10; v += 8; break;
431 case '9': v *= 10; v += 9; break;
447 * Parses a hex number including hex floats and set the
450 static void parse_number_hex(void)
452 assert(c == 'x' || c == 'X');
456 obstack_1grow(&symbol_obstack, (char) c);
459 obstack_1grow(&symbol_obstack, '\0');
460 char *string = obstack_finish(&symbol_obstack);
462 if(c == '.' || c == 'p' || c == 'P') {
464 panic("Hex floating point numbers not implemented yet");
466 if(*string == '\0') {
467 parse_error("invalid hex number");
468 lexer_token.type = T_ERROR;
472 lexer_token.type = T_INTEGER;
473 lexer_token.v.intvalue = parse_int_string(string, &endptr, 16);
474 if(*endptr != '\0') {
475 parse_error("hex number literal too long");
478 obstack_free(&symbol_obstack, string);
479 parse_integer_suffix(true);
483 * Returns true if the given char is a octal digit.
485 * @param char the character to check
487 static inline bool is_octal_digit(int chr)
505 * Parses a octal number and set the lexer_token.
507 static void parse_number_oct(void)
509 while(is_octal_digit(c)) {
510 obstack_1grow(&symbol_obstack, (char) c);
513 obstack_1grow(&symbol_obstack, '\0');
514 char *string = obstack_finish(&symbol_obstack);
517 lexer_token.type = T_INTEGER;
518 lexer_token.v.intvalue = parse_int_string(string, &endptr, 8);
519 if(*endptr != '\0') {
520 parse_error("octal number literal too long");
523 obstack_free(&symbol_obstack, string);
524 parse_integer_suffix(true);
528 * Parses a decimal including float number and set the
531 static void parse_number_dec(void)
533 bool is_float = false;
535 obstack_1grow(&symbol_obstack, (char) c);
540 obstack_1grow(&symbol_obstack, '.');
544 obstack_1grow(&symbol_obstack, (char) c);
549 if(c == 'e' || c == 'E') {
550 obstack_1grow(&symbol_obstack, 'e');
553 if(c == '-' || c == '+') {
554 obstack_1grow(&symbol_obstack, (char) c);
559 obstack_1grow(&symbol_obstack, (char) c);
565 obstack_1grow(&symbol_obstack, '\0');
566 char *string = obstack_finish(&symbol_obstack);
570 lexer_token.type = T_FLOATINGPOINT;
571 lexer_token.v.floatvalue = strtold(string, &endptr);
573 if(*endptr != '\0') {
574 parse_error("invalid number literal");
577 parse_floating_suffix();
580 lexer_token.type = T_INTEGER;
581 lexer_token.v.intvalue = parse_int_string(string, &endptr, 10);
583 if(*endptr != '\0') {
584 parse_error("invalid number literal");
587 parse_integer_suffix(false);
589 obstack_free(&symbol_obstack, string);
593 * Parses a number and sets the lexer_token.
595 static void parse_number(void)
617 parse_error("invalid octal number");
618 lexer_token.type = T_ERROR;
624 obstack_1grow(&symbol_obstack, '0');
634 * Returns the value of a digit.
635 * The only portable way to do it ...
637 static int digit_value(int digit) {
662 panic("wrong character given");
667 * Parses an octal character sequence.
669 * @param first_digit the already read first digit
671 static int parse_octal_sequence(const int first_digit)
673 assert(is_octal_digit(first_digit));
674 int value = digit_value(first_digit);
675 if (!is_octal_digit(c)) return value;
676 value = 8 * value + digit_value(c);
678 if (!is_octal_digit(c)) return value;
679 value = 8 * value + digit_value(c);
683 return (signed char) value;
685 return (unsigned char) value;
690 * Parses a hex character sequence.
692 static int parse_hex_sequence(void)
696 value = 16 * value + digit_value(c);
701 return (signed char) value;
703 return (unsigned char) value;
708 * Parse an escape sequence.
710 static int parse_escape_sequence(void)
718 case '"': return '"';
719 case '\'': return '\'';
720 case '\\': return '\\';
721 case '?': return '\?';
722 case 'a': return '\a';
723 case 'b': return '\b';
724 case 'f': return '\f';
725 case 'n': return '\n';
726 case 'r': return '\r';
727 case 't': return '\t';
728 case 'v': return '\v';
730 return parse_hex_sequence();
739 return parse_octal_sequence(ec);
741 parse_error("reached end of file while parsing escape sequence");
744 parse_error("unknown escape sequence");
750 * Concatenate two strings.
752 string_t concat_strings(const string_t *const s1, const string_t *const s2)
754 const size_t len1 = s1->size - 1;
755 const size_t len2 = s2->size - 1;
757 char *const concat = obstack_alloc(&symbol_obstack, len1 + len2 + 1);
758 memcpy(concat, s1->begin, len1);
759 memcpy(concat + len1, s2->begin, len2 + 1);
761 #if 0 /* TODO hash */
762 const char *result = strset_insert(&stringset, concat);
763 if(result != concat) {
764 obstack_free(&symbol_obstack, concat);
769 return (string_t){ concat, len1 + len2 + 1 };
774 * Concatenate a string and a wide string.
776 wide_string_t concat_string_wide_string(const string_t *const s1, const wide_string_t *const s2)
778 const size_t len1 = s1->size - 1;
779 const size_t len2 = s2->size - 1;
781 wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat));
782 const char *const src = s1->begin;
783 for (size_t i = 0; i != len1; ++i) {
786 memcpy(concat + len1, s2->begin, (len2 + 1) * sizeof(*concat));
788 return (wide_string_t){ concat, len1 + len2 + 1 };
792 * Concatenate two wide strings.
794 wide_string_t concat_wide_strings(const wide_string_t *const s1, const wide_string_t *const s2)
796 const size_t len1 = s1->size - 1;
797 const size_t len2 = s2->size - 1;
799 wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat));
800 memcpy(concat, s1->begin, len1 * sizeof(*concat));
801 memcpy(concat + len1, s2->begin, (len2 + 1) * sizeof(*concat));
803 return (wide_string_t){ concat, len1 + len2 + 1 };
807 * Concatenate a wide string and a string.
809 wide_string_t concat_wide_string_string(const wide_string_t *const s1, const string_t *const s2)
811 const size_t len1 = s1->size - 1;
812 const size_t len2 = s2->size - 1;
814 wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat));
815 memcpy(concat, s1->begin, len1 * sizeof(*concat));
816 const char *const src = s2->begin;
817 for (size_t i = 0; i != len2 + 1; ++i) {
821 return (wide_string_t){ concat, len1 + len2 + 1 };
825 * Parse a string literal and set lexer_token.
827 static void parse_string_literal(void)
829 const unsigned start_linenr = lexer_token.source_position.linenr;
837 tc = parse_escape_sequence();
838 obstack_1grow(&symbol_obstack, (char) tc);
842 source_position_t source_position;
843 source_position.input_name = lexer_token.source_position.input_name;
844 source_position.linenr = start_linenr;
845 errorf(source_position, "string has no end");
846 lexer_token.type = T_ERROR;
855 obstack_1grow(&symbol_obstack, (char) c);
863 /* TODO: concatenate multiple strings separated by whitespace... */
865 /* add finishing 0 to the string */
866 obstack_1grow(&symbol_obstack, '\0');
867 const size_t size = (size_t)obstack_object_size(&symbol_obstack);
868 const char *const string = obstack_finish(&symbol_obstack);
870 #if 0 /* TODO hash */
871 /* check if there is already a copy of the string */
872 result = strset_insert(&stringset, string);
873 if(result != string) {
874 obstack_free(&symbol_obstack, string);
877 const char *const result = string;
880 lexer_token.type = T_STRING_LITERAL;
881 lexer_token.v.string.begin = result;
882 lexer_token.v.string.size = size;
886 * Parse a wide character constant and set lexer_token.
888 static void parse_wide_character_constant(void)
896 found_char = parse_escape_sequence();
900 parse_error("newline while parsing character constant");
906 goto end_of_wide_char_constant;
909 parse_error("EOF while parsing character constant");
910 lexer_token.type = T_ERROR;
914 if(found_char != 0) {
915 parse_error("more than 1 characters in character "
917 goto end_of_wide_char_constant;
926 end_of_wide_char_constant:
927 lexer_token.type = T_INTEGER;
928 lexer_token.v.intvalue = found_char;
929 lexer_token.datatype = type_wchar_t;
933 * Parse a wide string literal and set lexer_token.
935 static void parse_wide_string_literal(void)
937 const unsigned start_linenr = lexer_token.source_position.linenr;
945 wchar_rep_t tc = parse_escape_sequence();
946 obstack_grow(&symbol_obstack, &tc, sizeof(tc));
951 source_position_t source_position;
952 source_position.input_name = lexer_token.source_position.input_name;
953 source_position.linenr = start_linenr;
954 errorf(source_position, "string has no end");
955 lexer_token.type = T_ERROR;
965 obstack_grow(&symbol_obstack, &tc, sizeof(tc));
974 /* TODO: concatenate multiple strings separated by whitespace... */
976 /* add finishing 0 to the string */
977 wchar_rep_t nul = L'\0';
978 obstack_grow(&symbol_obstack, &nul, sizeof(nul));
979 const size_t size = (size_t)obstack_object_size(&symbol_obstack) / sizeof(wchar_rep_t);
980 const wchar_rep_t *const string = obstack_finish(&symbol_obstack);
982 #if 0 /* TODO hash */
983 /* check if there is already a copy of the string */
984 const wchar_rep_t *const result = strset_insert(&stringset, string);
985 if(result != string) {
986 obstack_free(&symbol_obstack, string);
989 const wchar_rep_t *const result = string;
992 lexer_token.type = T_WIDE_STRING_LITERAL;
993 lexer_token.v.wide_string.begin = result;
994 lexer_token.v.wide_string.size = size;
998 * Parse a character constant and set lexer_token.
1000 static void parse_character_constant(void)
1002 const unsigned start_linenr = lexer_token.source_position.linenr;
1010 tc = parse_escape_sequence();
1011 obstack_1grow(&symbol_obstack, (char) tc);
1015 parse_error("newline while parsing character constant");
1020 source_position_t source_position;
1021 source_position.input_name = lexer_token.source_position.input_name;
1022 source_position.linenr = start_linenr;
1023 errorf(source_position, "EOF while parsing character constant");
1024 lexer_token.type = T_ERROR;
1030 goto end_of_char_constant;
1033 obstack_1grow(&symbol_obstack, (char) c);
1040 end_of_char_constant:;
1041 const size_t size = (size_t)obstack_object_size(&symbol_obstack);
1042 const char *const string = obstack_finish(&symbol_obstack);
1044 lexer_token.type = T_CHARS;
1045 lexer_token.v.string.begin = string;
1046 lexer_token.v.string.size = size;
1047 lexer_token.datatype = type_int;
1051 * Skip a multiline comment.
1053 static void skip_multiline_comment(void)
1055 unsigned start_linenr = lexer_token.source_position.linenr;
1062 /* TODO: nested comment, warn here */
1073 MATCH_NEWLINE(break;)
1076 source_position_t source_position;
1077 source_position.input_name = lexer_token.source_position.input_name;
1078 source_position.linenr = start_linenr;
1079 errorf(source_position, "at end of file while looking for comment end");
1091 * Skip a single line comment.
1093 static void skip_line_comment(void)
1111 /** The current preprocessor token. */
1112 static token_t pp_token;
1115 * Read the next preprocessor token.
1117 static inline void next_pp_token(void)
1119 lexer_next_preprocessing_token();
1120 pp_token = lexer_token;
1124 * Eat all preprocessor tokens until newline.
1126 static void eat_until_newline(void)
1128 while(pp_token.type != '\n' && pp_token.type != T_EOF) {
1134 * Handle the define directive.
1136 static void define_directive(void)
1138 lexer_next_preprocessing_token();
1139 if(lexer_token.type != T_IDENTIFIER) {
1140 parse_error("expected identifier after #define\n");
1141 eat_until_newline();
1146 * Handle the ifdef directive.
1148 static void ifdef_directive(int is_ifndef)
1151 lexer_next_preprocessing_token();
1152 //expect_identifier();
1157 * Handle the endif directive.
1159 static void endif_directive(void)
1165 * Parse the line directive.
1167 static void parse_line_directive(void)
1169 if(pp_token.type != T_INTEGER) {
1170 parse_error("expected integer");
1172 lexer_token.source_position.linenr = (unsigned int)(pp_token.v.intvalue - 1);
1175 if(pp_token.type == T_STRING_LITERAL) {
1176 lexer_token.source_position.input_name = pp_token.v.string.begin;
1180 eat_until_newline();
1190 STDC_CX_LIMITED_RANGE
1191 } stdc_pragma_kind_t;
1194 * STDC pragma values.
1201 } stdc_pragma_value_kind_t;
1204 * Parse a pragma directive.
1206 static void parse_pragma(void) {
1207 bool unknown_pragma = true;
1210 if (pp_token.v.symbol->pp_ID == TP_STDC) {
1211 stdc_pragma_kind_t kind = STDC_UNKNOWN;
1213 if (c_mode & _C99) {
1216 switch (pp_token.v.symbol->pp_ID) {
1217 case TP_FP_CONTRACT:
1218 kind = STDC_FP_CONTRACT;
1220 case TP_FENV_ACCESS:
1221 kind = STDC_FENV_ACCESS;
1223 case TP_CX_LIMITED_RANGE:
1224 kind = STDC_CX_LIMITED_RANGE;
1229 if (kind != STDC_UNKNOWN) {
1230 stdc_pragma_value_kind_t value = STDC_VALUE_UNKNOWN;
1232 switch (pp_token.v.symbol->pp_ID) {
1234 value = STDC_VALUE_ON;
1237 value = STDC_VALUE_OFF;
1240 value = STDC_VALUE_DEFAULT;
1245 if (value != STDC_VALUE_UNKNOWN) {
1246 unknown_pragma = false;
1248 errorf(pp_token.source_position, "bad STDC pragma argument");
1253 unknown_pragma = true;
1255 eat_until_newline();
1256 if (unknown_pragma && warning.unknown_pragmas) {
1257 warningf(pp_token.source_position, "encountered unknown #pragma");
1262 * Parse a preprocessor non-null directive.
1264 static void parse_preprocessor_identifier(void)
1266 assert(pp_token.type == T_IDENTIFIER);
1267 symbol_t *symbol = pp_token.v.symbol;
1269 switch(symbol->pp_ID) {
1271 printf("include - enable header name parsing!\n");
1287 parse_line_directive();
1294 /* TODO; output the rest of the line */
1295 parse_error("#error directive: ");
1304 * Parse a preprocessor directive.
1306 static void parse_preprocessor_directive(void)
1310 switch(pp_token.type) {
1312 parse_preprocessor_identifier();
1315 parse_line_directive();
1318 /* NULL directive, see § 6.10.7 */
1321 parse_error("invalid preprocessor directive");
1322 eat_until_newline();
1327 #define MAYBE_PROLOG \
1332 #define MAYBE(ch, set_type) \
1335 lexer_token.type = set_type; \
1338 #define ELSE_CODE(code) \
1342 } /* end of while(1) */ \
1345 #define ELSE(set_type) \
1347 lexer_token.type = set_type; \
1351 void lexer_next_preprocessing_token(void)
1361 lexer_token.type = '\n';
1367 /* might be a wide string ( L"string" ) */
1368 if(lexer_token.type == T_IDENTIFIER &&
1369 lexer_token.v.symbol == symbol_L) {
1371 parse_wide_string_literal();
1372 } else if(c == '\'') {
1373 parse_wide_character_constant();
1383 parse_string_literal();
1387 parse_character_constant();
1409 MAYBE('.', T_DOTDOTDOT)
1413 lexer_token.type = '.';
1419 MAYBE('&', T_ANDAND)
1420 MAYBE('=', T_ANDEQUAL)
1424 MAYBE('=', T_ASTERISKEQUAL)
1428 MAYBE('+', T_PLUSPLUS)
1429 MAYBE('=', T_PLUSEQUAL)
1433 MAYBE('>', T_MINUSGREATER)
1434 MAYBE('-', T_MINUSMINUS)
1435 MAYBE('=', T_MINUSEQUAL)
1439 MAYBE('=', T_EXCLAMATIONMARKEQUAL)
1443 MAYBE('=', T_SLASHEQUAL)
1446 skip_multiline_comment();
1447 lexer_next_preprocessing_token();
1451 skip_line_comment();
1452 lexer_next_preprocessing_token();
1457 MAYBE('>', T_PERCENTGREATER)
1458 MAYBE('=', T_PERCENTEQUAL)
1463 MAYBE(':', T_PERCENTCOLONPERCENTCOLON)
1467 lexer_token.type = T_PERCENTCOLON;
1470 ELSE(T_PERCENTCOLON)
1474 MAYBE(':', T_LESSCOLON)
1475 MAYBE('%', T_LESSPERCENT)
1476 MAYBE('=', T_LESSEQUAL)
1479 MAYBE('=', T_LESSLESSEQUAL)
1484 MAYBE('=', T_GREATEREQUAL)
1487 MAYBE('=', T_GREATERGREATEREQUAL)
1488 ELSE(T_GREATERGREATER)
1492 MAYBE('=', T_CARETEQUAL)
1496 MAYBE('=', T_PIPEEQUAL)
1497 MAYBE('|', T_PIPEPIPE)
1501 MAYBE('>', T_COLONGREATER)
1505 MAYBE('=', T_EQUALEQUAL)
1509 MAYBE('#', T_HASHHASH)
1523 lexer_token.type = c;
1528 lexer_token.type = T_EOF;
1533 errorf(lexer_token.source_position, "unknown character '%c' found\n", c);
1534 lexer_token.type = T_ERROR;
1540 void lexer_next_token(void)
1542 lexer_next_preprocessing_token();
1543 if(lexer_token.type != '\n')
1548 lexer_next_preprocessing_token();
1549 } while(lexer_token.type == '\n');
1551 if(lexer_token.type == '#') {
1552 parse_preprocessor_directive();
1557 void init_lexer(void)
1559 strset_init(&stringset);
1562 void lexer_open_stream(FILE *stream, const char *input_name)
1565 lexer_token.source_position.linenr = 0;
1566 lexer_token.source_position.input_name = input_name;
1568 symbol_L = symbol_table_insert("L");
1572 /* place a virtual \n at the beginning so the lexer knows that we're
1573 * at the beginning of a line */
1577 void exit_lexer(void)
1579 strset_destroy(&stringset);
1582 static __attribute__((unused))
1583 void dbg_pos(const source_position_t source_position)
1585 fprintf(stdout, "%s:%u\n", source_position.input_name,
1586 source_position.linenr);