stage1_2/iec_flex.ll
changeset 866 c8c48ab075e0
parent 793 268bf4ca5fa1
child 867 a435684a5223
equal deleted inserted replaced
865:7365c3e5c9ae 866:c8c48ab075e0
     3  *
     3  *
     4  *  Copyright (C) 2003-2011  Mario de Sousa (msousa@fe.up.pt)
     4  *  Copyright (C) 2003-2011  Mario de Sousa (msousa@fe.up.pt)
     5  *
     5  *
     6  *  This program is free software: you can redistribute it and/or modify
     6  *  This program is free software: you can redistribute it and/or modify
     7  *  it under the terms of the GNU General Public License as published by
     7  *  it under the terms of the GNU General Public License as published by
     8  *  the Free Software Foundation, either version 3 of the License, or
     8  *  the Free Software Foundation, either version 3 of thest_whitespaceLicense, or
     9  *  (at your option) any later version.
     9  *  (at your option) any later version.
    10  *
    10  *
    11  *  This program is distributed in the hope that it will be useful,
    11  *  This program is distributed in the hope that it will be useful,
    12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   354  * e.g.:  TIME#55d_4h_56m
   354  * e.g.:  TIME#55d_4h_56m
   355  *       We would like to return to bison the tokens 'TIME' '#' '55d' '_' '4h' '_' '56m'
   355  *       We would like to return to bison the tokens 'TIME' '#' '55d' '_' '4h' '_' '56m'
   356  *       Unfortunately, flex will join '_' and '4h' to create a legal {identifier} '_4h',
   356  *       Unfortunately, flex will join '_' and '4h' to create a legal {identifier} '_4h',
   357  *       and return that identifier instead! So, we added this state!
   357  *       and return that identifier instead! So, we added this state!
   358  *
   358  *
   359  * The state machine has 7 possible states (INITIAL, config, decl, body, st, il, sfc)
   359  * There is a main state machine (
       
   360  *    +------> INITIAL <-------> config
       
   361  *    |           \
       
   362  *    |           V
       
   363  *    |     header_state
       
   364  *    |           |
       
   365  *    |           V
       
   366  *    |  vardecl_list_state <------> var_decl
       
   367  *    |           | 
       
   368  *    |           V
       
   369  *    +----------body, 
       
   370  *                ^
       
   371  *                | 
       
   372  *    -----------------------
       
   373  *    |           |         |
       
   374  *    v           v         v
       
   375  *   st          il       sfc
       
   376  * 
   360  * Possible state changes are:
   377  * Possible state changes are:
   361  *   INITIAL -> goto(decl_state)
       
   362  *               (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found,
       
   363  *                and followed by a VAR declaration)
       
   364  *   INITIAL -> goto(body_state) 
       
   365  *                (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found,
       
   366  *                 and _not_ followed by a VAR declaration)
       
   367  *                (This transition is actually commented out, since the syntax
       
   368  *                 does not allow the declaration of functions, FBs, or programs
       
   369  *                 without any VAR declaration!)
       
   370  *   INITIAL -> goto(config_state)
   378  *   INITIAL -> goto(config_state)
   371  *                (when a CONFIGURATION is found)
   379  *                (when a CONFIGURATION is found)
   372  *   decl_state    -> push(decl_state); goto(body_state)
   380  * 
   373  *                     (when the last END_VAR is found, i.e. the function body starts)
   381  *   INITIAL -> goto(header_state)
   374  *   decl_state    -> push(decl_state); goto(sfc_state)
   382  *               (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found)
       
   383  *   header_state -> goto(vardecl_list_state)
       
   384  *               (When the first VAR token is found, i.e. at begining of first VAR .. END_VAR declaration)
       
   385  * 
       
   386  *  vardecl_list_state -> push current state (vardecl_list_state), and goto(vardecl_state) 
       
   387  *                (when a VAR token is found)
       
   388  *   vardecl_state -> pop() to (vardecl_list_state) 
       
   389  *                (when a END_VAR token is found)
       
   390  * 
       
   391  *   vardecl_list_state -> goto(body_state) 
       
   392  *                (when the last END_VAR is found!)
       
   393  *
       
   394  *   body_state    -> push current state(body_state); goto(sfc_state)
   375  *                     (when it figures out it is parsing sfc language)
   395  *                     (when it figures out it is parsing sfc language)
   376  *   body_state    -> goto(st_state)
   396  *   body_state    -> push current state(body_state); goto(st_state)
   377  *                     (when it figures out it is parsing st language)
   397  *                     (when it figures out it is parsing st language)
   378  *   body_state    -> goto(il_state)
   398  *   body_state    -> push current state(body_state); goto(il_state)
   379  *                     (when it figures out it is parsing il language)
   399  *                     (when it figures out it is parsing il language)
   380  *   st_state      -> pop()
   400  *   st_state      -> pop() to body_sate
   381  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   401  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   382  *                      END_ACTION or END_TRANSITION is found)
   402  *                      END_ACTION or END_TRANSITION is found)
   383  *   il_state      -> pop()
   403  *   il_state      -> pop() to body_sate
   384  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   404  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   385  *                      END_ACTION or END_TRANSITION is found)
   405  *                      END_ACTION or END_TRANSITION is found)
   386  *   decl_state    -> goto(INITIAL)
   406  *   sfc_state     -> pop() to body_sate
   387  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   407  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   388  *   sfc_state     -> goto(INITIAL)
   408  * 
       
   409  *   body_sate -> goto(INITIAL)
   389  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   410  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   390  *   config_state  -> goto(INITIAL)
   411  *   config_state  -> goto(INITIAL)
   391  *                     (when a END_CONFIGURATION is found)
   412  *                     (when a END_CONFIGURATION is found)
   392  *   sfc_state     -> push(sfc_state); goto(body_state)
   413  * 
       
   414  *  
       
   415  *   sfc_state     -> push current state(sfc_state); goto(body_state)
   393  *                     (when parsing an action. This transition is requested by bison)
   416  *                     (when parsing an action. This transition is requested by bison)
   394  *   sfc_state     -> push(sfc_state); goto(sfc_qualifier_state)
   417  *   sfc_state     -> push current state(sfc_state); goto(sfc_qualifier_state)
   395  *                     (when expecting an action qualifier. This transition is requested by bison)
   418  *                     (when expecting an action qualifier. This transition is requested by bison)
   396  *   sfc_qualifier_state -> pop()
   419  *   sfc_qualifier_state -> pop() to sfc_state
   397  *                     (when no longer expecting an action qualifier. This transition is requested by bison)
   420  *                     (when no longer expecting an action qualifier. This transition is requested by bison)
       
   421  *
   398  *   config_state  -> push(config_state); goto(task_init_state)
   422  *   config_state  -> push(config_state); goto(task_init_state)
   399  *                     (when parsing a task initialisation. This transition is requested by bison)
   423  *                     (when parsing a task initialisation. This transition is requested by bison)
   400  *   task_init_state -> pop()
   424  *   task_init_state -> pop()
   401  *                     (when no longer parsing task initialisation parameters. This transition is requested by bison)
   425  *                     (when no longer parsing task initialisation parameters. This transition is requested by bison)
   402  *
   426  *
       
   427  * 
       
   428  * There is another secondary state machine for parsing comments, another for file_includes, 
       
   429  * and yet another for time literals.
   403  */
   430  */
   404 
   431 
   405 
   432 
   406 /* we are parsing a configuration. */
   433 /* we are parsing a configuration. */
   407 %s config_state
   434 %s config_state
   411  * tokens, and not as possible identifiers. Note that the above words
   438  * tokens, and not as possible identifiers. Note that the above words
   412  * are not keywords.
   439  * are not keywords.
   413  */
   440  */
   414 %s task_init_state
   441 %s task_init_state
   415 
   442 
   416 /* we are parsing a function, program or function block declaration */
   443 /* we are looking for the first VAR inside a function's, program's or function block's declaration */
   417 %s decl_state
   444 %s header_state
       
   445 
       
   446 /* we are parsing a function, program or function block sequence of VAR..END_VAR delcarations */
       
   447 %x vardecl_list_state 
       
   448 /* a substate of the vardecl_list_state: we are inside a specific VAR .. END_VAR */
       
   449 %s vardecl_state
   418 
   450 
   419 /* we will be parsing a function body. Whether il/st/sfc remains to be determined */
   451 /* we will be parsing a function body. Whether il/st/sfc remains to be determined */
   420 %x body_state
   452 %x body_state
   421 
   453 
   422 /* we are parsing il code -> flex must return the EOL tokens!       */
   454 /* we are parsing il code -> flex must return the EOL tokens!       */
   434 /* we are parsing sfc code, and expecting the priority token.       */
   466 /* we are parsing sfc code, and expecting the priority token.       */
   435 %s sfc_priority_state
   467 %s sfc_priority_state
   436 
   468 
   437 /* we are parsing a TIME# literal. We must not return any {identifier} tokens. */
   469 /* we are parsing a TIME# literal. We must not return any {identifier} tokens. */
   438 %x time_literal_state
   470 %x time_literal_state
       
   471 
       
   472 /* we are parsing a comment. */
       
   473 %x comment_state
   439 
   474 
   440 
   475 
   441 /*******************/
   476 /*******************/
   442 /* File #include's */
   477 /* File #include's */
   443 /*******************/
   478 /*******************/
   453 %x include_filename
   488 %x include_filename
   454 %x include_end
   489 %x include_end
   455 
   490 
   456 
   491 
   457 file_include_pragma_filename	[^\"]*
   492 file_include_pragma_filename	[^\"]*
   458 file_include_pragma_beg		"{#include"{st_whitespace_only}\"
   493 file_include_pragma_beg		"{#include"{st_whitespace}\"
   459 file_include_pragma_end		\"{st_whitespace_only}"}"
   494 file_include_pragma_end		\"{st_whitespace}"}"
   460 file_include_pragma			{file_include_pragma_beg}{file_include_pragma_filename}{file_include_pragma_end}
   495 file_include_pragma			{file_include_pragma_beg}{file_include_pragma_filename}{file_include_pragma_end}
   461 
   496 
   462 
   497 
   463 %{
   498 %{
   464 #define MAX_INCLUDE_DEPTH 16
   499 #define MAX_INCLUDE_DEPTH 16
   497 
   532 
   498 /*****************************/
   533 /*****************************/
   499 /* Prelimenary constructs... */
   534 /* Prelimenary constructs... */
   500 /*****************************/
   535 /*****************************/
   501 
   536 
       
   537 /* PRAGMAS */
       
   538 /* ======= */
   502 /* In order to allow the declaration of POU prototypes (Function, FB, Program, ...),
   539 /* In order to allow the declaration of POU prototypes (Function, FB, Program, ...),
   503  * especially the prototypes of Functions and FBs defined in the standard
   540  * especially the prototypes of Functions and FBs defined in the standard
   504  * (i.e. standard functions and FBs), we extend the IEC 61131-3 standard syntax 
   541  * (i.e. standard functions and FBs), we extend the IEC 61131-3 standard syntax 
   505  * with two pragmas to indicate that the code is to be parsed (going through the 
   542  * with two pragmas to indicate that the code is to be parsed (going through the 
   506  * lexical, syntactical, and semantic analysers), but no code is to be generated.
   543  * lexical, syntactical, and semantic analysers), but no code is to be generated.
   519 disable_code_generation_pragma	"{disable code generation}"
   556 disable_code_generation_pragma	"{disable code generation}"
   520 enable_code_generation_pragma	"{enable code generation}"
   557 enable_code_generation_pragma	"{enable code generation}"
   521 
   558 
   522 
   559 
   523 /* Any other pragma... */
   560 /* Any other pragma... */
   524 
       
   525 pragma "{"[^}]*"}"|"{{"([^}]|"}"[^}])*"}}"
   561 pragma "{"[^}]*"}"|"{{"([^}]|"}"[^}])*"}}"
   526 
   562 /*
       
   563 pragma "{"[^}]*"}"
       
   564 */
       
   565 
       
   566 /* COMMENTS */
       
   567 /* ======== */
       
   568 
       
   569 /* In order to allow nested comments, comments are handled by a specific comment_state state */
       
   570 /* Whenever a "(*" is found, we push the current state onto the stack, and enter a new instance of the comment_state state.
       
   571  * Whenever a "*)" is found, we pop a state off the stack
       
   572  */
       
   573 
       
   574 /* comments... */
       
   575 comment_beg  "(*"
       
   576 comment_end  "*)"
       
   577 
       
   578 /* However, bison has a shift/reduce conflict in bison, when parsing formal function/FB
       
   579  * invocations with the 'NOT <variable_name> =>' syntax (which needs two look ahead 
       
   580  * tokens to be parsed correctly - and bison being LALR(1) only supports one).
       
   581  * The current work around requires flex to completely parse the '<variable_name> =>'
       
   582  * sequence. This sequence includes whitespace and/or comments between the 
       
   583  * <variable_name> and the "=>" token.
       
   584  * 
       
   585  * This flex rule (sendto_identifier_token) uses the whitespace/comment as trailing context,
       
   586  * which means we can not use the comment_state method of specifying/finding and ignoring 
       
   587  * comments.
       
   588  * 
       
   589  * For this reason only, we must also define what a complete comment looks like, so
       
   590  * it may be used in this rule. Since the rule uses the whitespace_or_comment
       
   591  * construct as trailing context, this definition of comment must not use any
       
   592  * trailing context either.
       
   593  * 
       
   594  * Aditionally, it is not possible to define nested comments in flex without the use of
       
   595  * states, so for this particular location, we do NOT support nested comments.
       
   596  */
   527 /* NOTE: this seemingly unnecessary complex definition is required
   597 /* NOTE: this seemingly unnecessary complex definition is required
   528  *       to be able to eat up comments such as:
   598  *       to be able to eat up comments such as:
   529  *          '(* Testing... ! ***** ******)'
   599  *          '(* Testing... ! ***** ******)'
   530  *       without using the trailing context command in flex (/{context})
   600  *       without using the trailing context command in flex (/{context})
   531  *       since {comment} itself will later be used with
   601  *       since {comment} itself will later be used with
   532  *       trailing context ({comment}/{context})
   602  *       trailing context ({comment}/{context})
   533  */
   603  */
   534 not_asterisk				[^*]
   604 not_asterisk				[^*]
   535 not_close_parenthesis_nor_asterisk	[^*)]
   605 not_close_parenthesis_nor_asterisk	[^*)]
   536 asterisk				"*"
   606 asterisk				"*"
   537 comment_text		{not_asterisk}|(({asterisk}+){not_close_parenthesis_nor_asterisk})
   607 comment_text	({not_asterisk})|(({asterisk}+){not_close_parenthesis_nor_asterisk})
   538 
       
   539 comment		"(*"({comment_text}*)({asterisk}+)")"
   608 comment		"(*"({comment_text}*)({asterisk}+)")"
   540 
   609 
   541 
   610 
       
   611 
       
   612 /* 3.1 Whitespace */
       
   613 /* ============== */
   542 /*
   614 /*
   543 3.1 Whitespace
   615  * Whitespace is clearly defined (see IEC 61131-3 v2, section 2.1.4)
   544  (NOTE: Whitespace IS clearly defined, to include newline!!! See section 2.1.4!!!)
   616  * 
   545  No definition of whitespace is given, in other words, the characters that may be used to seperate language tokens are not pecisely defined. One may nevertheless make an inteligent guess of using the space (' '), and other characters also commonly considered whitespace in other programming languages (horizontal tab, vertical tab, form feed, etc.).
   617  * Whitespace definition includes the newline character.
   546  The main question is whether the newline character should be considered whitespace. IL language statements use an EOL token (End Of Line) to distinguish between some language constructs. The EOL token itself is openly defined as "normally consist[ing] of the 'paragraph separator' ", leaving the final choice open to each implemention. If we choose the newline character to represent the EOL token, it may then not be considered whitespace.
   618  * 
   547  On the other hand, some examples that come in a non-normative annex of the specification allow function declarations to span multiple3.1 Whitespace
   619  * However, the standard is inconsistent in that in IL the newline character 
   548  (NOTE: Whitespace IS clearly defined, to include newline!!! See section 2.1.4!!!)
   620  * is considered a token (EOL - end of line). 
   549  No definition of whitespace is given, in other words, the characters that may be used to seperate language tokens are not pecisely defined. One may nevertheless make an inteligent guess of using the space (' '), and other characters also commonly considered whitespace in other programming languages (horizontal tab, vertical tab, form feed, etc.).
   621  * In our implementation we therefore have two definitions of whitespace
   550  The main question is whether the newline character should be considered whitespace. IL language statements use an EOL token (End Of Line) to distinguish between some language constructs. The EOL token itself is openly defined as "normally consist[ing] of the 'paragraph separator' ", leaving the final choice open to each implemention. If we choose the newline character to represent the EOL token, it may then not be considered whitespace.
   622  *   - one for ST, that includes the newline character
   551  On the other hand, some examples that come in a non-normative annex of the specification allow function declarations to span multiple lines, which means that the newline character is being considered as whitespace.
   623  *   - one for IL without the newline character.
   552  Our implementation works around this issue by including the new line character in the whitespace while parsing function declarations and the ST language, and parsing it as the EOL token only while parsing IL language statements. This requires the use of a state machine in the lexical parser that needs at least some knowledge of the syntax itself.
   624  * Additionally, when parsing IL, the newline character is treated as the EOL token.
   553 */
   625  * This requires the use of a state machine in the lexical parser that needs at least 
   554 /* NOTE: Our definition of whitespace will only work in ASCII!
   626  * some knowledge of the syntax itself.
   555  *
   627  *
   556  *       Since the IL language needs to know the location of newline
   628  * NOTE: Our definition of whitespace will only work in ASCII!
   557  *       (token EOL -> '\n' ), we need one definition of whitespace
   629  *
   558  *       for each language...
       
   559  */
       
   560 /*
       
   561  * NOTE: we cannot use
   630  * NOTE: we cannot use
   562  *         st_whitespace	[:space:]*
   631  *         st_whitespace	[:space:]*
   563  *       since we use {st_whitespace} as trailing context. In our case
   632  *       since we use {st_whitespace} as trailing context. In our case
   564  *       this would not constitute "dangerous trailing context", but the
   633  *       this would not constitute "dangerous trailing context", but the
   565  *       lexical generator (i.e. flex) does not know this (since it does
   634  *       lexical generator (i.e. flex) does not know this (since it does
   567  *       generate a "dangerous trailing context" warning!
   636  *       generate a "dangerous trailing context" warning!
   568  *       We use this alternative just to stop the flex utility from
   637  *       We use this alternative just to stop the flex utility from
   569  *       generating the invalid (in this case) warning...
   638  *       generating the invalid (in this case) warning...
   570  */
   639  */
   571 
   640 
   572 st_whitespace_only	[ \f\n\r\t\v]*
   641 st_whitespace			[ \f\n\r\t\v]*
   573 il_whitespace_only	[ \f\r\t\v]*
   642 il_whitespace			[ \f\r\t\v]*
   574 
   643 
   575 st_whitespace_text	{st_whitespace_only}|{comment}|{pragma}
   644 st_whitespace_or_pragma_or_commentX	({st_whitespace})|({pragma})|({comment})
   576 il_whitespace_text	{il_whitespace_only}|{comment}|{pragma}
   645 il_whitespace_or_pragma_or_commentX	({il_whitespace})|({pragma})|({comment})
   577 
   646 
   578 st_whitespace	{st_whitespace_text}*
   647 st_whitespace_or_pragma_or_comment	{st_whitespace_or_pragma_or_commentX}*
   579 il_whitespace	{il_whitespace_text}*
   648 il_whitespace_or_pragma_or_comment	{il_whitespace_or_pragma_or_commentX}*
   580 
   649 
   581 st_whitespace_text_no_pragma	{st_whitespace_only}|{comment}
   650 
   582 il_whitespace_text_no_pragma	{il_whitespace_only}|{comment}
   651 
   583 
   652 qualified_identifier	{identifier}(\.{identifier})+
   584 st_whitespace_no_pragma	{st_whitespace_text_no_pragma}*
       
   585 il_whitespace_no_pragma	{il_whitespace_text_no_pragma}*
       
   586 
       
   587 qualified_identifier	{identifier}(\.{identifier})*
       
   588 
   653 
   589 
   654 
   590 
   655 
   591 /*****************************************/
   656 /*****************************************/
   592 /* B.1.1 Letters, digits and identifiers */
   657 /* B.1.1 Letters, digits and identifiers */
   851 <INITIAL>{file_include_pragma}	unput_text(0); yy_push_state(include_beg);
   916 <INITIAL>{file_include_pragma}	unput_text(0); yy_push_state(include_beg);
   852 
   917 
   853 	/* Pragmas sent to syntax analyser (bison) */
   918 	/* Pragmas sent to syntax analyser (bison) */
   854 {disable_code_generation_pragma}               return disable_code_generation_pragma_token;
   919 {disable_code_generation_pragma}               return disable_code_generation_pragma_token;
   855 {enable_code_generation_pragma}                return enable_code_generation_pragma_token;
   920 {enable_code_generation_pragma}                return enable_code_generation_pragma_token;
   856 <body_state>{disable_code_generation_pragma}   return disable_code_generation_pragma_token;
   921 <body_state,vardecl_list_state>{disable_code_generation_pragma}   return disable_code_generation_pragma_token;
   857 <body_state>{enable_code_generation_pragma}    return enable_code_generation_pragma_token;
   922 <body_state,vardecl_list_state>{enable_code_generation_pragma}    return enable_code_generation_pragma_token;
   858 
   923 
   859 	/* Any other pragma we find, we just pass it up to the syntax parser...   */
   924 	/* Any other pragma we find, we just pass it up to the syntax parser...   */
   860 	/* Note that the <body_state> state is exclusive, so we have to include it here too. */
   925 	/* Note that the <body_state> state is exclusive, so we have to include it here too. */
   861 {pragma}	{/* return the pragmma without the enclosing '{' and '}' */
   926 {pragma}	{/* return the pragmma without the enclosing '{' and '}' */
   862          int cut = yytext[1]=='{'?2:1;
   927          int cut = yytext[1]=='{'?2:1;
   863 		 yytext[strlen(yytext)-cut] = '\0';
   928 		 yytext[strlen(yytext)-cut] = '\0';
   864 		 yylval.ID=strdup(yytext+cut);
   929 		 yylval.ID=strdup(yytext+cut);
   865 		 return pragma_token;
   930 		 return pragma_token;
   866 		}
   931 		}
   867 <body_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */
   932 <body_state,vardecl_list_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */
   868 		 int cut = yytext[1]=='{'?2:1;
   933 		 int cut = yytext[1]=='{'?2:1;
   869          yytext[strlen(yytext)-cut] = '\0';
   934 		 yytext[strlen(yytext)-cut] = '\0';
   870 		 yylval.ID=strdup(yytext+cut);
   935 		 yylval.ID=strdup(yytext+cut);
   871 		 return pragma_token;
   936 		 return pragma_token;
   872 		}
   937 		}
   873 
   938 
   874 
   939 
   948 
  1013 
   949 	/*********************************/
  1014 	/*********************************/
   950 	/* Handle all the state changes! */
  1015 	/* Handle all the state changes! */
   951 	/*********************************/
  1016 	/*********************************/
   952 
  1017 
   953 	/* INITIAL -> decl_state */
  1018 	/* INITIAL -> header_state */
   954 <INITIAL>{
  1019 <INITIAL>{
   955 	/* NOTE: how about functions that do not declare variables, and go directly to the body_state???
  1020 	/* NOTE: how about functions that do not declare variables, and go directly to the body_state???
   956 	 *      - According to Section 2.5.1.3 (Function Declaration), item 2 in the list, a FUNCTION
  1021 	 *      - According to Section 2.5.1.3 (Function Declaration), item 2 in the list, a FUNCTION
   957 	 *        must have at least one input argument, so a correct declaration will have at least
  1022 	 *        must have at least one input argument, so a correct declaration will have at least
   958 	 *        one VAR_INPUT ... VAR_END construct!
  1023 	 *        one VAR_INPUT ... VAR_END construct!
   964 	 *        construct!
  1029 	 *        construct!
   965 	 *
  1030 	 *
   966 	 *       All the above means that we needn't worry about PROGRAMs, FUNCTIONs or
  1031 	 *       All the above means that we needn't worry about PROGRAMs, FUNCTIONs or
   967 	 *       FUNCTION_BLOCKs that do not have at least one VAR_END before the body_state.
  1032 	 *       FUNCTION_BLOCKs that do not have at least one VAR_END before the body_state.
   968 	 *       If the code has an error, and no VAR_END before the body, we will simply
  1033 	 *       If the code has an error, and no VAR_END before the body, we will simply
   969 	 *       continue in the <decl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK
  1034 	 *       continue in the <vardecl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK
   970 	 *       or PROGAM.
  1035 	 *       or PROGAM.
   971 	 */
  1036 	 */
   972 FUNCTION				BEGIN(decl_state); return FUNCTION;
  1037 FUNCTION				BEGIN(header_state); return FUNCTION;
   973 FUNCTION_BLOCK				BEGIN(decl_state); return FUNCTION_BLOCK;
  1038 FUNCTION_BLOCK				BEGIN(header_state); return FUNCTION_BLOCK;
   974 PROGRAM					BEGIN(decl_state); return PROGRAM;
  1039 PROGRAM					BEGIN(header_state); return PROGRAM;
   975 CONFIGURATION				BEGIN(config_state); return CONFIGURATION;
  1040 CONFIGURATION				BEGIN(config_state); return CONFIGURATION;
   976 }
  1041 }
   977 
  1042 
   978 	/* INITIAL -> body_state */
  1043 	/* INITIAL -> body_state */
   979 	/* required if the function, program, etc.. has no VAR block! */
  1044 	/* required if the function, program, etc.. has no VAR block! */
   987 FUNCTION_BLOCK	BEGIN(body_state); return FUNCTION_BLOCK;
  1052 FUNCTION_BLOCK	BEGIN(body_state); return FUNCTION_BLOCK;
   988 PROGRAM		BEGIN(body_state); return PROGRAM;
  1053 PROGRAM		BEGIN(body_state); return PROGRAM;
   989 }
  1054 }
   990 	*/
  1055 	*/
   991 
  1056 
   992 	/* decl_state -> (body_state | sfc_state) */
  1057 	/* header_state -> (vardecl_state | body_state) */
   993 <decl_state>{
  1058 <header_state>{
   994 END_VAR{st_whitespace}VAR		{unput_text(strlen("END_VAR")); 
  1059 VAR				unput_text(0); BEGIN(vardecl_list_state);
   995 					 return END_VAR;
  1060 }
   996 					}
  1061 
   997 END_VAR{st_whitespace}INITIAL_STEP	{unput_text(strlen("END_VAR")); 
  1062 
   998 					 yy_push_state(sfc_state); 
  1063 <vardecl_list_state>{
   999 					 return END_VAR;
  1064 VAR				unput_text(0); yy_push_state(vardecl_state);
  1000 					}
  1065 .				unput_text(0); BEGIN(body_state); /* anything else, just change to body_state! */
  1001 END_VAR{st_whitespace}			{unput_text(strlen("END_VAR")); 
  1066 }
  1002 					 cmd_goto_body_state(); 
  1067 
  1003 					 return END_VAR;
  1068 
  1004 					}
  1069 <vardecl_state>{
  1005 }
  1070 END_VAR				yy_pop_state(); return END_VAR; /* pop back to header_state */
       
  1071 }
       
  1072 
  1006 
  1073 
  1007 	/* body_state -> (il_state | st_state) */
  1074 	/* body_state -> (il_state | st_state) */
  1008 <body_state>{
  1075 <body_state>{
  1009 {st_whitespace_no_pragma}			/* Eat any whitespace */
  1076 END_FUNCTION			BEGIN(INITIAL); return END_FUNCTION;
  1010 {qualified_identifier}{st_whitespace}":="	unput_text(0); BEGIN(st_state);
  1077 END_FUNCTION_BLOCK		BEGIN(INITIAL); return END_FUNCTION_BLOCK;
  1011 {direct_variable_standard}{st_whitespace}":="	unput_text(0); BEGIN(st_state);
  1078 END_PROGRAM			BEGIN(INITIAL); return END_PROGRAM;
  1012 {qualified_identifier}"["			unput_text(0); BEGIN(st_state);
  1079 
  1013 
  1080 INITIAL_STEP			unput_text(0); yy_push_state(sfc_state); 
  1014 RETURN						unput_text(0); BEGIN(st_state);
  1081 
  1015 IF						unput_text(0); BEGIN(st_state);
  1082 {qualified_identifier}		unput_text(0); yy_push_state(st_state); /* will always be followed by '[' for an array access, or ':=' as the left hand of an assignment statement */
  1016 CASE						unput_text(0); BEGIN(st_state);
  1083 {direct_variable_standard}	unput_text(0); yy_push_state(st_state); /* will always be followed by ':=' as the left hand of an assignment statement */
  1017 FOR						unput_text(0); BEGIN(st_state);
  1084 
  1018 WHILE						unput_text(0); BEGIN(st_state);
  1085 RETURN				unput_text(0); yy_push_state(st_state);
  1019 REPEAT						unput_text(0); BEGIN(st_state);
  1086 IF				unput_text(0); yy_push_state(st_state);
  1020 EXIT						unput_text(0); BEGIN(st_state);
  1087 CASE				unput_text(0); yy_push_state(st_state);
       
  1088 FOR				unput_text(0); yy_push_state(st_state);
       
  1089 WHILE				unput_text(0); yy_push_state(st_state);
       
  1090 EXIT				unput_text(0); yy_push_state(st_state);
       
  1091 REPEAT				unput_text(0); yy_push_state(st_state);
  1021 
  1092 
  1022 	/* ':=' occurs only in transitions, and not Function or FB bodies! */
  1093 	/* ':=' occurs only in transitions, and not Function or FB bodies! */
  1023 :=						unput_text(0); BEGIN(st_state);
  1094 :=				unput_text(0); yy_push_state(st_state);
  1024 
       
  1025 	/* Hopefully, the above rules (along with the last one),
       
  1026          * used to distinguish ST from IL, are 
       
  1027 	 * enough to handle all ocurrences. However, if
       
  1028 	 * there is some situation where the compiler is getting confused,
       
  1029 	 * we add the following rule to detect 'label:' in IL code. This will
       
  1030 	 * allow the user to insert a label right at the beginning (which
       
  1031 	 * will probably not be used further by his code) simply as a way
       
  1032 	 * to force the compiler to interpret his code as IL code.
       
  1033 	 */
       
  1034 {identifier}{st_whitespace}":"{st_whitespace}	unput_text(0); BEGIN(il_state);
       
  1035 
  1095 
  1036 {identifier}	{int token = get_identifier_token(yytext);
  1096 {identifier}	{int token = get_identifier_token(yytext);
  1037 		 if (token == prev_declared_fb_name_token) {
  1097 		 if ((token == prev_declared_fb_name_token) || (token == prev_declared_variable_name_token)) {
  1038 		   /* the code has a call to a function block */
  1098 		   /* the code has a call to a function block OR has an assingment with a variable as the lvalue */
  1039 		   /* NOTE: if we ever decide to allow the user to use IL operator tokens
  1099 		   unput_text(0); yy_push_state(st_state);
  1040 		    * (LD, ST, ...) as identifiers for variable names (including
  1100 		 } else
  1041 		    * function block instances), then the above inference/conclusion 
  1101  		 if (token == prev_declared_derived_function_name_token) {
  1042 		    * may be incorrect, and this condition may have to be changed!
  1102 		   /* the code has a call to a function - must be IL */
  1043 		    */	
  1103 		   unput_text(0); yy_push_state(il_state);
  1044 		   BEGIN(st_state);
       
  1045 		 } else {
  1104 		 } else {
  1046 		   BEGIN(il_state);
  1105 		   /* Might be a lable in IL, or a bug in ST/IL code. We jump to IL */
       
  1106 		   unput_text(0); yy_push_state(il_state);
  1047 		 }
  1107 		 }
  1048 		 unput_text(0);
       
  1049 		}
  1108 		}
  1050 
  1109 
  1051 .		unput_text(0); BEGIN(il_state);
  1110 .		unput_text(0); yy_push_state(il_state); /* Don't know what it could be. This is most likely a bug. Let's just to a random state... */
  1052 }	/* end of body_state lexical parser */
  1111 }	/* end of body_state lexical parser */
  1053 
  1112 
  1054 	/* (il_state | st_state) -> $previous_state (decl_state or sfc_state) */
  1113 
       
  1114 
       
  1115 	/* (il_state | st_state) -> $previous_state (vardecl_state or sfc_state) */
  1055 <il_state,st_state>{
  1116 <il_state,st_state>{
  1056 END_FUNCTION		yy_pop_state(); unput_text(0);
  1117 END_FUNCTION		yy_pop_state(); unput_text(0);
  1057 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1118 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1058 END_PROGRAM		yy_pop_state(); unput_text(0);
  1119 END_PROGRAM		yy_pop_state(); unput_text(0);
  1059 END_TRANSITION		yy_pop_state(); unput_text(0);
  1120 END_TRANSITION		yy_pop_state(); unput_text(0);
  1065 END_FUNCTION		yy_pop_state(); unput_text(0);
  1126 END_FUNCTION		yy_pop_state(); unput_text(0);
  1066 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1127 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1067 END_PROGRAM		yy_pop_state(); unput_text(0);
  1128 END_PROGRAM		yy_pop_state(); unput_text(0);
  1068 }
  1129 }
  1069 
  1130 
  1070 	/* decl_state -> INITIAL */
       
  1071 <decl_state>{
       
  1072 END_FUNCTION		BEGIN(INITIAL); return END_FUNCTION;
       
  1073 END_FUNCTION_BLOCK	BEGIN(INITIAL); return END_FUNCTION_BLOCK;
       
  1074 END_PROGRAM		BEGIN(INITIAL); return END_PROGRAM;
       
  1075 }
       
  1076 	/* config -> INITIAL */
  1131 	/* config -> INITIAL */
  1077 END_CONFIGURATION	BEGIN(INITIAL); return END_CONFIGURATION;
  1132 END_CONFIGURATION	BEGIN(INITIAL); return END_CONFIGURATION;
  1078 
  1133 
  1079 
  1134 
  1080 
  1135 
  1081 	/***************************************/
  1136 	/***************************************/
  1082 	/* Next is to to remove all whitespace */
  1137 	/* Next is to to remove all whitespace */
  1083 	/***************************************/
  1138 	/***************************************/
  1084 	/* NOTE: pragmas are handled right at the beginning... */
  1139 	/* NOTE: pragmas are handled right at the beginning... */
  1085 
  1140 
  1086 <INITIAL,config_state,decl_state,st_state,sfc_state,task_init_state,sfc_qualifier_state>{st_whitespace_no_pragma}	/* Eat any whitespace */
  1141 	/* The whitespace */
  1087 <il_state>{il_whitespace_no_pragma}		/* Eat any whitespace */
  1142 <INITIAL,header_state,config_state,body_state,vardecl_list_state,vardecl_state,st_state,sfc_state,task_init_state,sfc_qualifier_state>{st_whitespace}	/* Eat any whitespace */
  1088 
  1143 <il_state>{il_whitespace}		/* Eat any whitespace */
  1089 
  1144 
       
  1145 	/* The comments */
       
  1146 <body_state,vardecl_list_state>{comment_beg}	yy_push_state(comment_state);
       
  1147 {comment_beg}							yy_push_state(comment_state);
       
  1148 <comment_state>{
       
  1149 {comment_beg}							yy_push_state(comment_state);
       
  1150 {comment_end}							yy_pop_state();
       
  1151 .								/* Ignore text inside comment! */
       
  1152 \n								/* Ignore text inside comment! */
       
  1153 }
  1090 
  1154 
  1091 	/*****************************************/
  1155 	/*****************************************/
  1092 	/* B.1.1 Letters, digits and identifiers */
  1156 	/* B.1.1 Letters, digits and identifiers */
  1093 	/*****************************************/
  1157 	/*****************************************/
  1094 	/* NOTE: 'R1', 'IN', etc... are IL operators, and therefore tokens
  1158 	/* NOTE: 'R1', 'IN', etc... are IL operators, and therefore tokens
  1637 
  1701 
  1638 
  1702 
  1639 	/*****************************************/
  1703 	/*****************************************/
  1640 	/* B.1.1 Letters, digits and identifiers */
  1704 	/* B.1.1 Letters, digits and identifiers */
  1641 	/*****************************************/
  1705 	/*****************************************/
  1642 <st_state>{identifier}/({st_whitespace})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
  1706 <st_state>{identifier}/({st_whitespace_or_pragma_or_comment})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
  1643 <il_state>{identifier}/({il_whitespace})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
  1707 <il_state>{identifier}/({il_whitespace_or_pragma_or_comment})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
  1644 {identifier} 				{yylval.ID=strdup(yytext);
  1708 {identifier} 				{yylval.ID=strdup(yytext);
  1645 					 // printf("returning identifier...: %s, %d\n", yytext, get_identifier_token(yytext));
  1709 					 // printf("returning identifier...: %s, %d\n", yytext, get_identifier_token(yytext));
  1646 					 return get_identifier_token(yytext);}
  1710 					 return get_identifier_token(yytext);}
  1647 
  1711 
  1648 
  1712