stage1_2/iec_flex.ll
changeset 757 f1fc4aa6f0e3
parent 756 634f476cb60f
child 761 7b52623a2f37
equal deleted inserted replaced
756:634f476cb60f 757:f1fc4aa6f0e3
   142  * where the value of the tokens will be stored
   142  * where the value of the tokens will be stored
   143  */
   143  */
   144 extern YYSTYPE yylval;
   144 extern YYSTYPE yylval;
   145 
   145 
   146 /* The name of the file currently being parsed...
   146 /* The name of the file currently being parsed...
   147  * This variable is declared and read from the code generated by bison!
       
   148  * Note that flex accesses and updates this global variable
   147  * Note that flex accesses and updates this global variable
   149  * apropriately whenever it comes across an (*#include <filename> *)
   148  * apropriately whenever it comes across an (*#include <filename> *) directive...
   150  * directive...
   149  */
   151  */
   150 const char *current_filename = NULL;
   152 /*
   151 
   153  NOTE: already defined in iec_bison.h 
       
   154 extern const char *current_filename;
       
   155 */
       
   156 
   152 
   157 
   153 
   158 /* We will not be using unput() in our flex code... */
   154 /* We will not be using unput() in our flex code... */
   159 /* NOTE: it seems that this #define is no longer needed, It has been 
   155 /* NOTE: it seems that this #define is no longer needed, It has been 
   160  * replaced by %option nounput.
   156  * replaced by %option nounput.
   247  * but first return to the stream an additional character to mark the end of the token. 
   243  * but first return to the stream an additional character to mark the end of the token. 
   248  */
   244  */
   249 void unput_and_mark(const char c);
   245 void unput_and_mark(const char c);
   250 
   246 
   251 void include_file(const char *include_filename);
   247 void include_file(const char *include_filename);
       
   248 
       
   249 int GetNextChar(char *b, int maxBuffer);
   252 %}
   250 %}
   253 
   251 
   254 
   252 
   255 
   253 
   256 /****************************/
   254 /****************************/
   464 
   462 
   465 %{
   463 %{
   466 #define MAX_INCLUDE_DEPTH 16
   464 #define MAX_INCLUDE_DEPTH 16
   467 
   465 
   468 typedef struct {
   466 typedef struct {
       
   467     int eof;
       
   468     int lineNumber;
       
   469     int currentChar;
       
   470     int lineLength;
       
   471     int currentTokenStart;
       
   472     char *buffer;
       
   473     FILE *in_file;
       
   474   } tracking_t;
       
   475 
       
   476 typedef struct {
   469 	  YY_BUFFER_STATE buffer_state;
   477 	  YY_BUFFER_STATE buffer_state;
   470 	  tracking_t* env;
   478 	  tracking_t *env;
   471 	  const char *filename;
   479 	  const char *filename;
   472 	} include_stack_t;
   480 	} include_stack_t;
   473 
   481 
   474 tracking_t* current_tracking;
   482 tracking_t *current_tracking = NULL;
   475 include_stack_t include_stack[MAX_INCLUDE_DEPTH];
   483 include_stack_t include_stack[MAX_INCLUDE_DEPTH];
   476 int include_stack_ptr = 0;
   484 int include_stack_ptr = 0;
   477 
   485 
   478 const char *INCLUDE_DIRECTORIES[] = {
   486 const char *INCLUDE_DIRECTORIES[] = {
   479 	DEFAULT_LIBDIR,
   487 	DEFAULT_LIBDIR,
   481 	"/lib",
   489 	"/lib",
   482 	"/usr/lib",
   490 	"/usr/lib",
   483 	"/usr/lib/iec",
   491 	"/usr/lib/iec",
   484 	NULL /* must end with NULL!! */
   492 	NULL /* must end with NULL!! */
   485 	};
   493 	};
   486 
       
   487 %}
   494 %}
   488 
   495 
   489 
   496 
   490 
   497 
   491 /*****************************/
   498 /*****************************/
   883 			       *       If we have finished parsing the main file, then we
   890 			       *       If we have finished parsing the main file, then we
   884 			       *       must leave include_stack_ptr at 0, in case the 
   891 			       *       must leave include_stack_ptr at 0, in case the 
   885 			       *       parser is called once again with a new file.
   892 			       *       parser is called once again with a new file.
   886 			       *       (In fact, we currently do just that!)
   893 			       *       (In fact, we currently do just that!)
   887 			       */
   894 			       */
       
   895 			  fclose(yyin);
   888 			  free(current_tracking);
   896 			  free(current_tracking);
   889 			  if (include_stack_ptr == 0) {
   897 			  if (include_stack_ptr == 0) {
   890 			      /* yyterminate() terminates the scanner and returns a 0 to the 
   898 			      /* yyterminate() terminates the scanner and returns a 0 to the 
   891 			       * scanner's  caller, indicating "all done".
   899 			       * scanner's  caller, indicating "all done".
   892 			       *	
   900 			       *	
   982 }
   990 }
   983 
   991 
   984 	/* body_state -> (il_state | st_state) */
   992 	/* body_state -> (il_state | st_state) */
   985 <body_state>{
   993 <body_state>{
   986 {st_whitespace_no_pragma}			/* Eat any whitespace */
   994 {st_whitespace_no_pragma}			/* Eat any whitespace */
   987 {qualified_identifier}{st_whitespace}":="	  unput_text(0); BEGIN(st_state);
   995 {qualified_identifier}{st_whitespace}":="	unput_text(0); BEGIN(st_state);
   988 {direct_variable_standard}{st_whitespace}":="	  unput_text(0); BEGIN(st_state);
   996 {direct_variable_standard}{st_whitespace}":="	unput_text(0); BEGIN(st_state);
   989 {qualified_identifier}"["			unput_text(0); BEGIN(st_state);
   997 {qualified_identifier}"["			unput_text(0); BEGIN(st_state);
   990 
   998 
   991 RETURN					unput_text(0); BEGIN(st_state);
   999 RETURN						unput_text(0); BEGIN(st_state);
   992 IF							unput_text(0); BEGIN(st_state);
  1000 IF						unput_text(0); BEGIN(st_state);
   993 CASE						unput_text(0); BEGIN(st_state);
  1001 CASE						unput_text(0); BEGIN(st_state);
   994 FOR							unput_text(0); BEGIN(st_state);
  1002 FOR						unput_text(0); BEGIN(st_state);
   995 WHILE						unput_text(0); BEGIN(st_state);
  1003 WHILE						unput_text(0); BEGIN(st_state);
   996 REPEAT					unput_text(0); BEGIN(st_state);
  1004 REPEAT						unput_text(0); BEGIN(st_state);
   997 EXIT						unput_text(0); BEGIN(st_state);
  1005 EXIT						unput_text(0); BEGIN(st_state);
   998 
  1006 
   999 	/* ':=' occurs only in transitions, and not Function or FB bodies! */
  1007 	/* ':=' occurs only in transitions, and not Function or FB bodies! */
  1000 :=							unput_text(0); BEGIN(st_state);
  1008 :=						unput_text(0); BEGIN(st_state);
  1001 
  1009 
  1002 	/* Hopefully, the above rules (along with the last one),
  1010 	/* Hopefully, the above rules (along with the last one),
  1003          * used to distinguish ST from IL, are 
  1011          * used to distinguish ST from IL, are 
  1004 	 * enough to handle all ocurrences. However, if
  1012 	 * enough to handle all ocurrences. However, if
  1005 	 * there is some situation where the compiler is getting confused,
  1013 	 * there is some situation where the compiler is getting confused,
  1647 
  1655 
  1648 
  1656 
  1649 %%
  1657 %%
  1650 
  1658 
  1651 
  1659 
       
  1660 /*************************/
       
  1661 /* Tracking Functions... */
       
  1662 /*************************/
       
  1663 
       
  1664 #define MAX_BUFFER_LENGTH 1000
       
  1665 
       
  1666 tracking_t *GetNewTracking(FILE* in_file) {
       
  1667   tracking_t* new_env = new tracking_t;
       
  1668   new_env->eof = 0;
       
  1669   new_env->lineNumber = 0;
       
  1670   new_env->currentChar = 0;
       
  1671   new_env->lineLength = 0;
       
  1672   new_env->currentTokenStart = 0;
       
  1673   new_env->buffer = (char*)malloc(MAX_BUFFER_LENGTH);
       
  1674   new_env->in_file = in_file;
       
  1675   return new_env;
       
  1676 }
       
  1677 
       
  1678 
       
  1679 /* GetNextChar: reads a character from input */
       
  1680 int GetNextChar(char *b, int maxBuffer) {
       
  1681   char *p;
       
  1682   
       
  1683   if (  current_tracking->eof  )
       
  1684     return 0;
       
  1685   
       
  1686   while (  current_tracking->currentChar >= current_tracking->lineLength  ) {
       
  1687     current_tracking->currentChar = 0;
       
  1688     current_tracking->currentTokenStart = 1;
       
  1689     current_tracking->eof = false;
       
  1690     
       
  1691     p = fgets(current_tracking->buffer, MAX_BUFFER_LENGTH, current_tracking->in_file);
       
  1692     if (  p == NULL  ) {
       
  1693       if (  ferror(current_tracking->in_file)  )
       
  1694         return 0;
       
  1695       current_tracking->eof = true;
       
  1696       return 0;
       
  1697     }
       
  1698     
       
  1699     current_tracking->lineNumber++;
       
  1700     current_tracking->lineLength = strlen(current_tracking->buffer);
       
  1701   }
       
  1702   
       
  1703   b[0] = current_tracking->buffer[current_tracking->currentChar];
       
  1704   if (b[0] == ' ' || b[0] == '\t')
       
  1705     current_tracking->currentTokenStart++;
       
  1706   current_tracking->currentChar++;
       
  1707 
       
  1708   return b[0]==0?0:1;
       
  1709 }
       
  1710 
       
  1711 
       
  1712 
       
  1713 
  1652 /***********************************/
  1714 /***********************************/
  1653 /* Utility function definitions... */
  1715 /* Utility function definitions... */
  1654 /***********************************/
  1716 /***********************************/
  1655 
  1717 
  1656 /* print the include file stack to stderr... */
  1718 /* print the include file stack to stderr... */
  1689 
  1751 
  1690 
  1752 
  1691 /* insert the code (in <source_code>) into the source code we are parsing.
  1753 /* insert the code (in <source_code>) into the source code we are parsing.
  1692  * This is done by creating an artificial file with that new source code, and then 'including' the file
  1754  * This is done by creating an artificial file with that new source code, and then 'including' the file
  1693  */
  1755  */
  1694 void include_string(const char *source_code) {
  1756 void include_string_(const char *source_code) {
  1695   FILE *tmp_file = tmpfile();
  1757   FILE *tmp_file = tmpfile();
  1696   
  1758   
  1697   if(tmp_file == NULL) {
  1759   if(tmp_file == NULL) {
  1698     perror("Error creating temp file.");
  1760     perror("Error creating temp file.");
  1699     exit(EXIT_FAILURE);
  1761     exit(EXIT_FAILURE);
  1788   return 1;  /* Stop scanning at end of input file. */
  1850   return 1;  /* Stop scanning at end of input file. */
  1789 }
  1851 }
  1790 
  1852 
  1791 
  1853 
  1792 
  1854 
       
  1855 /*******************************/
       
  1856 /* Public Interface for Bison. */
       
  1857 /*******************************/
       
  1858 
       
  1859 /* The following functions will be called from inside bison code! */
       
  1860 
       
  1861 void include_string(const char *source_code) {include_string_(source_code);}
       
  1862 
       
  1863 
       
  1864 /* Tell flex which file to parse. This function will not imediately start parsing the file.
       
  1865  * To parse the file, you then need to call yyparse()
       
  1866  *
       
  1867  * Returns -1 on error opening the file (and a valid errno), or 0 on success.
       
  1868  */
       
  1869 int parse_file(const char *filename) {
       
  1870   FILE *filehandle = NULL;
       
  1871 
       
  1872   if((filehandle = fopen(filename, "r")) == NULL) 
       
  1873     return -1;
       
  1874 
       
  1875   yyin = filehandle;
       
  1876   current_filename = strdup(filename);
       
  1877   current_tracking = GetNewTracking(yyin);
       
  1878   return 0;
       
  1879 }
       
  1880 
       
  1881 
       
  1882 
       
  1883 
       
  1884 
       
  1885 
  1793 /*************************************/
  1886 /*************************************/
  1794 /* Include a main() function to test */
  1887 /* Include a main() function to test */
  1795 /* the token parsing by flex....     */
  1888 /* the token parsing by flex....     */
  1796 /*************************************/
  1889 /*************************************/
  1797 #ifdef TEST_MAIN
  1890 #ifdef TEST_MAIN
  1799 #include "../util/symtable.hh"
  1892 #include "../util/symtable.hh"
  1800 
  1893 
  1801 yystype yylval;
  1894 yystype yylval;
  1802 YYLTYPE yylloc;
  1895 YYLTYPE yylloc;
  1803 
  1896 
  1804 const char *current_filename;
       
  1805 
  1897 
  1806 
  1898 
  1807 
  1899 
  1808 int get_identifier_token(const char *identifier_str) {return 0;}
  1900 int get_identifier_token(const char *identifier_str) {return 0;}
  1809 int get_direct_variable_token(const char *direct_variable_str) {return 0;}
  1901 int get_direct_variable_token(const char *direct_variable_str) {return 0;}