153 * track of the locations, in order to give |
153 * track of the locations, in order to give |
154 * more meaningful error messages! |
154 * more meaningful error messages! |
155 */ |
155 */ |
156 extern YYLTYPE yylloc; |
156 extern YYLTYPE yylloc; |
157 |
157 |
|
158 #define YY_INPUT(buf,result,max_size) {\ |
|
159 result = GetNextChar(buf, max_size);\ |
|
160 if ( result <= 0 )\ |
|
161 result = YY_NULL;\ |
|
162 } |
|
163 |
158 /* Macro that is executed for every action. |
164 /* Macro that is executed for every action. |
159 * We use it to pass the location of the token |
165 * We use it to pass the location of the token |
160 * back to the bison parser... |
166 * back to the bison parser... |
161 */ |
167 */ |
162 #define YY_USER_ACTION { \ |
168 #define YY_USER_ACTION {\ |
163 yylloc.first_line = yylloc.last_line = yylineno; \ |
169 yylloc.first_line = current_tracking->lineNumber;\ |
164 yylloc.first_column = yylloc.last_column = 0; \ |
170 yylloc.first_column = current_tracking->currentTokenStart;\ |
|
171 yylloc.last_line = current_tracking->lineNumber;\ |
|
172 yylloc.last_column = current_tracking->currentChar - 1;\ |
|
173 current_tracking->currentTokenStart = current_tracking->currentChar;\ |
165 } |
174 } |
166 |
175 |
167 |
176 |
168 /* Since this lexical parser we defined only works in ASCII based |
177 /* Since this lexical parser we defined only works in ASCII based |
169 * systems, we might as well make sure it is being compiled on |
178 * systems, we might as well make sure it is being compiled on |
402 %{ |
411 %{ |
403 #define MAX_INCLUDE_DEPTH 16 |
412 #define MAX_INCLUDE_DEPTH 16 |
404 |
413 |
405 typedef struct { |
414 typedef struct { |
406 YY_BUFFER_STATE buffer_state; |
415 YY_BUFFER_STATE buffer_state; |
407 int lineno; |
416 tracking_t* env; |
408 const char *filename; |
417 const char *filename; |
409 } include_stack_t; |
418 } include_stack_t; |
410 |
419 |
|
420 tracking_t* current_tracking; |
411 include_stack_t include_stack[MAX_INCLUDE_DEPTH]; |
421 include_stack_t include_stack[MAX_INCLUDE_DEPTH]; |
412 int include_stack_ptr = 0; |
422 int include_stack_ptr = 0; |
413 |
423 |
414 const char *INCLUDE_DIRECTORIES[] = { |
424 const char *INCLUDE_DIRECTORIES[] = { |
415 DEFAULT_LIBDIR, |
425 DEFAULT_LIBDIR, |
522 letter [A-Za-z] |
532 letter [A-Za-z] |
523 digit [0-9] |
533 digit [0-9] |
524 octal_digit [0-7] |
534 octal_digit [0-7] |
525 hex_digit {digit}|[A-F] |
535 hex_digit {digit}|[A-F] |
526 identifier ({letter}|(_({letter}|{digit})))((_?({letter}|{digit}))*) |
536 identifier ({letter}|(_({letter}|{digit})))((_?({letter}|{digit}))*) |
527 |
537 invalid_identifier ({letter}|{digit}|_)* |
528 |
538 |
529 /*******************/ |
539 /*******************/ |
530 /* B.1.2 Constants */ |
540 /* B.1.2 Constants */ |
531 /*******************/ |
541 /*******************/ |
532 |
542 |
743 |
752 |
744 if (include_stack_ptr >= MAX_INCLUDE_DEPTH) { |
753 if (include_stack_ptr >= MAX_INCLUDE_DEPTH) { |
745 fprintf(stderr, "Includes nested too deeply\n"); |
754 fprintf(stderr, "Includes nested too deeply\n"); |
746 exit( 1 ); |
755 exit( 1 ); |
747 } |
756 } |
748 |
757 include_stack[include_stack_ptr].buffer_state = YY_CURRENT_BUFFER; |
749 (include_stack[include_stack_ptr]).buffer_state = YY_CURRENT_BUFFER; |
758 include_stack[include_stack_ptr].env = current_tracking; |
750 (include_stack[include_stack_ptr]).lineno = yylineno; |
759 include_stack[include_stack_ptr].filename = current_filename; |
751 (include_stack[include_stack_ptr]).filename = current_filename; |
760 |
752 include_stack_ptr++; |
|
753 yylineno = 1; |
|
754 current_filename = strdup(yytext); |
|
755 |
|
756 for (i = 0, yyin = NULL; (INCLUDE_DIRECTORIES[i] != NULL) && (yyin == NULL); i++) { |
761 for (i = 0, yyin = NULL; (INCLUDE_DIRECTORIES[i] != NULL) && (yyin == NULL); i++) { |
757 char *full_name = strdup3(INCLUDE_DIRECTORIES[i], "/", yytext); |
762 char *full_name = strdup3(INCLUDE_DIRECTORIES[i], "/", yytext); |
758 if (full_name == NULL) { |
763 if (full_name == NULL) { |
759 fprintf(stderr, "Out of memory!\n"); |
764 fprintf(stderr, "Out of memory!\n"); |
760 exit( 1 ); |
765 exit( 1 ); |
766 if (!yyin) { |
771 if (!yyin) { |
767 fprintf(stderr, "Error opening included file %s\n", yytext); |
772 fprintf(stderr, "Error opening included file %s\n", yytext); |
768 exit( 1 ); |
773 exit( 1 ); |
769 } |
774 } |
770 |
775 |
|
776 current_filename = strdup(yytext); |
|
777 current_tracking = GetNewTracking(yyin); |
|
778 include_stack_ptr++; |
|
779 |
771 /* switch input buffer to new file... */ |
780 /* switch input buffer to new file... */ |
772 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); |
781 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); |
773 /* switch to whatever state was active before the include file */ |
782 /* switch to whatever state was active before the include file */ |
774 yy_pop_state(); |
783 yy_pop_state(); |
775 /* now process the new file... */ |
784 /* now process the new file... */ |
782 * If we have finished parsing the main file, then we |
791 * If we have finished parsing the main file, then we |
783 * must leave include_stack_ptr at 0, in case the |
792 * must leave include_stack_ptr at 0, in case the |
784 * parser is called once again with a new file. |
793 * parser is called once again with a new file. |
785 * (In fact, we currently do just that!) |
794 * (In fact, we currently do just that!) |
786 */ |
795 */ |
|
796 free(current_tracking); |
787 if (include_stack_ptr == 0) { |
797 if (include_stack_ptr == 0) { |
788 /* yyterminate() terminates the scanner and returns a 0 to the |
798 /* yyterminate() terminates the scanner and returns a 0 to the |
789 * scanner's caller, indicating "all done". |
799 * scanner's caller, indicating "all done". |
790 * |
800 * |
791 * Our syntax parser (written with bison) has the token |
801 * Our syntax parser (written with bison) has the token |
794 * calling yyterminate() is equivalent to doing that. |
804 * calling yyterminate() is equivalent to doing that. |
795 */ |
805 */ |
796 yyterminate(); |
806 yyterminate(); |
797 } |
807 } |
798 else { |
808 else { |
799 --include_stack_ptr; |
809 --include_stack_ptr; |
800 yy_delete_buffer(YY_CURRENT_BUFFER); |
810 yy_delete_buffer(YY_CURRENT_BUFFER); |
801 yy_switch_to_buffer((include_stack[include_stack_ptr]).buffer_state); |
811 yy_switch_to_buffer((include_stack[include_stack_ptr]).buffer_state); |
802 yylineno = include_stack[include_stack_ptr].lineno; |
812 current_tracking = include_stack[include_stack_ptr].env; |
803 /* removing constness of char *. This is safe actually, |
813 /* removing constness of char *. This is safe actually, |
804 * since the only real const char * that is stored on the stack is |
814 * since the only real const char * that is stored on the stack is |
805 * the first one (i.e. the one that gets stored in include_stack[0], |
815 * the first one (i.e. the one that gets stored in include_stack[0], |
806 * which is never free'd! |
816 * which is never free'd! |
807 */ |
817 */ |
1489 int i; |
1500 int i; |
1490 |
1501 |
1491 if ((include_stack_ptr - 1) >= 0) |
1502 if ((include_stack_ptr - 1) >= 0) |
1492 fprintf (stderr, "in file "); |
1503 fprintf (stderr, "in file "); |
1493 for (i = include_stack_ptr - 1; i >= 0; i--) |
1504 for (i = include_stack_ptr - 1; i >= 0; i--) |
1494 fprintf (stderr, "included from file %s:%d\n", include_stack[i].filename, include_stack[i].lineno); |
1505 fprintf (stderr, "included from file %s:%d\n", include_stack[i].filename, include_stack[i].env->lineNumber); |
1495 } |
1506 } |
1496 |
1507 |
1497 |
1508 |
1498 /* return all the text in the current token back to the input stream, except the first n chars. */ |
1509 /* return all the text in the current token back to the input stream, except the first n chars. */ |
1499 void unput_text(unsigned int n) { |
1510 void unput_text(unsigned int n) { |
1501 * if we return newlines back to the input stream. These newlines will be re-counted |
1512 * if we return newlines back to the input stream. These newlines will be re-counted |
1502 * a second time when they are processed again by flex. |
1513 * a second time when they are processed again by flex. |
1503 * We therefore determine how many newlines are in the text we are returning, |
1514 * We therefore determine how many newlines are in the text we are returning, |
1504 * and decrement the line counter acordingly... |
1515 * and decrement the line counter acordingly... |
1505 */ |
1516 */ |
1506 unsigned int i; |
1517 /*unsigned int i; |
1507 unsigned int line_number = 0; |
1518 |
1508 int before_yylineno = yylineno; |
|
1509 |
|
1510 for (i = n; i < strlen(yytext); i++) |
1519 for (i = n; i < strlen(yytext); i++) |
1511 if (yytext[i] == '\n') |
1520 if (yytext[i] == '\n') |
1512 line_number++; |
1521 current_tracking->lineNumber--;*/ |
1513 |
1522 |
1514 /* now return all the text back to the input stream... */ |
1523 /* now return all the text back to the input stream... */ |
1515 yyless(n); |
1524 yyless(n); |
1516 |
|
1517 if (line_number > 0 && before_yylineno == yylineno) |
|
1518 yylineno = yylineno - line_number; |
|
1519 } |
1525 } |
1520 |
1526 |
1521 |
1527 |
1522 /* Called by flex when it reaches the end-of-file */ |
1528 /* Called by flex when it reaches the end-of-file */ |
1523 int yywrap(void) |
1529 int yywrap(void) |
1562 |
1568 |
1563 int main(int argc, char **argv) { |
1569 int main(int argc, char **argv) { |
1564 |
1570 |
1565 FILE *in_file; |
1571 FILE *in_file; |
1566 int res; |
1572 int res; |
1567 |
1573 |
1568 if (argc == 1) { |
1574 if (argc == 1) { |
1569 /* Work as an interactive (command line) parser... */ |
1575 /* Work as an interactive (command line) parser... */ |
1570 while((res=yylex())) |
1576 while((res=yylex())) |
1571 fprintf(stderr, "(line %d)token: %d\n", yylineno, res); |
1577 fprintf(stderr, "(line %d)token: %d\n", yylineno, res); |
1572 } else { |
1578 } else { |