stage1_2/iec_flex.ll
changeset 952 e984cfdf3b10
parent 948 543f8319bdf8
child 1010 242907849850
equal deleted inserted replaced
951:f53ea4c8621c 952:e984cfdf3b10
   345  * e.g.:  TIME#55d_4h_56m
   345  * e.g.:  TIME#55d_4h_56m
   346  *       We would like to return to bison the tokens 'TIME' '#' '55d' '_' '4h' '_' '56m'
   346  *       We would like to return to bison the tokens 'TIME' '#' '55d' '_' '4h' '_' '56m'
   347  *       Unfortunately, flex will join '_' and '4h' to create a legal {identifier} '_4h',
   347  *       Unfortunately, flex will join '_' and '4h' to create a legal {identifier} '_4h',
   348  *       and return that identifier instead! So, we added this state!
   348  *       and return that identifier instead! So, we added this state!
   349  *
   349  *
   350  * There is a main state machine...
   350  * The ignore_pou_state state is only used when bison says it is doing the pre-parsing.
       
   351  * During pre-parsing, the main state machine will only transition between
       
   352  * INITIAL and ignore_pou_state, and from here back to INITIAL. All other
       
   353  * transitions are inhibited. This inhibition is actually just enforced by making
       
   354  * sure that the INITIAL ---> ignore_pou_state transition is tested before all other
       
   355  * transitions coming out of INITIAL state. All other transitions are unaffected, as they
       
   356  * never get a chance to be evaluated when bison is doing pre-parsing.
       
   357  * Pre-parsing is a first quick scan through the whole input source code simply
       
   358  * to determine the list of POUs and datatypes that will be defined in that
       
   359  * code. Basically, the objective is to fill up the previously_declared_xxxxx
       
   360  * maps, without processing the code itself. Once these maps have been filled up,
       
   361  * bison will throw away the AST (abstract syntax tree) created up to that point, 
       
   362  * and scan through the same source code again, but this time creating a correct AST.
       
   363  * This pre-scan allows the source code to reference POUs and datatypes that are
       
   364  * only declared after they are used!
   351  * 
   365  * 
       
   366  *
       
   367  * Here is a main state machine...
       
   368  *                                                                         --+  
       
   369  *                                                                           |  these states are
       
   370  *              +------------> get_pou_name_state  ----> ignore_pou_state    |  only active 
       
   371  *              |                                            |               |  when bison is 
       
   372  *              |  ------------------------------------------+               |  doing the 
       
   373  *              |  |                                                         |  pre-parsing!!
       
   374  *              |  v                                                       --+
   352  *       +---> INITIAL <-------> config
   375  *       +---> INITIAL <-------> config
   353  *       |        \
   376  *       |        \
   354  *       |        V
   377  *       |        V
   355  *       |   header_state
   378  *       |   header_state
   356  *       |        |
   379  *       |        |
   377  *      - The transitions form sfc to body will be decided by bison, which will
   400  *      - The transitions form sfc to body will be decided by bison, which will
   378  *        tell flex to do the transition by calling cmd_goto_body_state().
   401  *        tell flex to do the transition by calling cmd_goto_body_state().
   379  *   
   402  *   
   380  * 
   403  * 
   381  * Possible state changes are:
   404  * Possible state changes are:
       
   405  *   INITIAL -> goto(ignore_pou_state)
       
   406  *               (This transition state is only used when bison says it is doing the pre-parsing.)
       
   407  *               (This transition takes precedence over all other transitions!)
       
   408  *               (when a FUNCTION, FUNCTION_BLOCK, PROGRAM or CONFIGURATION is found)
       
   409  * 
   382  *   INITIAL -> goto(config_state)
   410  *   INITIAL -> goto(config_state)
   383  *                (when a CONFIGURATION is found)
   411  *                (when a CONFIGURATION is found)
   384  * 
   412  * 
   385  *   INITIAL -> goto(header_state)
   413  *   INITIAL -> goto(header_state)
   386  *               (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found)
   414  *               (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found)
       
   415  * 
   387  *   header_state -> goto(vardecl_list_state)
   416  *   header_state -> goto(vardecl_list_state)
   388  *               (When the first VAR token is found, i.e. at begining of first VAR .. END_VAR declaration)
   417  *               (When the first VAR token is found, i.e. at begining of first VAR .. END_VAR declaration)
   389  * 
   418  * 
   390  *  vardecl_list_state -> push current state (vardecl_list_state), and goto(vardecl_state) 
   419  *  vardecl_list_state -> push current state (vardecl_list_state), and goto(vardecl_state) 
   391  *                (when a VAR token is found)
   420  *                (when a VAR token is found)
   408  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   437  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   409  *                      END_ACTION or END_TRANSITION is found)
   438  *                      END_ACTION or END_TRANSITION is found)
   410  *   sfc_state     -> pop() to vardecl_list_state
   439  *   sfc_state     -> pop() to vardecl_list_state
   411  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   440  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   412  * 
   441  * 
       
   442  *   ignore_pou_state   -> goto(INITIAL)
       
   443  *                         (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM or END_CONFIGURATION is found)
   413  *   vardecl_list_state -> goto(INITIAL)
   444  *   vardecl_list_state -> goto(INITIAL)
   414  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   445  *                         (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   415  *   config_state  -> goto(INITIAL)
   446  *   config_state       -> goto(INITIAL)
   416  *                     (when a END_CONFIGURATION is found)
   447  *                         (when a END_CONFIGURATION is found)
   417  * 
   448  * 
   418  *  
   449  *  
   419  *   sfc_state     -> push current state(sfc_state); goto(body_state)
   450  *   sfc_state     -> push current state(sfc_state); goto(body_state)
   420  *                     (when parsing an action. This transition is requested by bison)
   451  *                     (when parsing an action. This transition is requested by bison)
   421  *   sfc_state     -> push current state(sfc_state); goto(sfc_qualifier_state)
   452  *   sfc_state     -> push current state(sfc_state); goto(sfc_qualifier_state)
   431  * 
   462  * 
   432  * There is another secondary state machine for parsing comments, another for file_includes, 
   463  * There is another secondary state machine for parsing comments, another for file_includes, 
   433  * and yet another for time literals.
   464  * and yet another for time literals.
   434  */
   465  */
   435 
   466 
       
   467 
       
   468 /* Bison is in the pre-parsing stage, and we are parsing a POU. Ignore everything up to the end of the POU! */
       
   469 %x ignore_pou_state
       
   470 %x get_pou_name_state
   436 
   471 
   437 /* we are parsing a configuration. */
   472 /* we are parsing a configuration. */
   438 %s config_state
   473 %s config_state
   439 
   474 
   440 /* Inside a configuration, we are parsing a task initialisation parameters */
   475 /* Inside a configuration, we are parsing a task initialisation parameters */
  1050 	 *       FUNCTION_BLOCKs that do not have at least one VAR_END before the body_state.
  1085 	 *       FUNCTION_BLOCKs that do not have at least one VAR_END before the body_state.
  1051 	 *       If the code has an error, and no VAR_END before the body, we will simply
  1086 	 *       If the code has an error, and no VAR_END before the body, we will simply
  1052 	 *       continue in the <vardecl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK
  1087 	 *       continue in the <vardecl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK
  1053 	 *       or PROGAM.
  1088 	 *       or PROGAM.
  1054 	 */
  1089 	 */
  1055 FUNCTION				BEGIN(header_state); return FUNCTION;
  1090 
  1056 FUNCTION_BLOCK				BEGIN(header_state); return FUNCTION_BLOCK;
  1091 FUNCTION{st_whitespace} 		if (get_preparse_state()) BEGIN(get_pou_name_state); else BEGIN(header_state); return FUNCTION;
  1057 PROGRAM					BEGIN(header_state); return PROGRAM;
  1092 FUNCTION_BLOCK{st_whitespace}		if (get_preparse_state()) BEGIN(get_pou_name_state); else BEGIN(header_state); return FUNCTION_BLOCK;
  1058 CONFIGURATION				BEGIN(config_state); return CONFIGURATION;
  1093 PROGRAM{st_whitespace}			if (get_preparse_state()) BEGIN(get_pou_name_state); else BEGIN(header_state); return PROGRAM;
       
  1094 CONFIGURATION{st_whitespace}		if (get_preparse_state()) BEGIN(get_pou_name_state); else BEGIN(config_state); return CONFIGURATION;
       
  1095 }
       
  1096 
       
  1097 <get_pou_name_state>{
       
  1098 {identifier}			BEGIN(ignore_pou_state); yylval.ID=strdup(yytext); return identifier_token;
       
  1099 .				BEGIN(ignore_pou_state); unput_text(0);
       
  1100 }
       
  1101 
       
  1102 <ignore_pou_state>{
       
  1103 END_FUNCTION			unput_text(0); BEGIN(INITIAL);
       
  1104 END_FUNCTION_BLOCK		unput_text(0); BEGIN(INITIAL); 
       
  1105 END_PROGRAM			unput_text(0); BEGIN(INITIAL); 
       
  1106 END_CONFIGURATION		unput_text(0); BEGIN(INITIAL); 
       
  1107 .|\n				{}/* Ignore text inside POU! (including the '\n' character!)) */
  1059 }
  1108 }
  1060 
  1109 
  1061 	/* INITIAL -> body_state */
  1110 	/* INITIAL -> body_state */
  1062 	/* required if the function, program, etc.. has no VAR block! */
  1111 	/* required if the function, program, etc.. has no VAR block! */
  1063 	/* We comment it out since the standard does not allow this.  */
  1112 	/* We comment it out since the standard does not allow this.  */
  1178 	/* The whitespace */
  1227 	/* The whitespace */
  1179 <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 */
  1228 <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 */
  1180 <il_state>{il_whitespace}		/* Eat any whitespace */
  1229 <il_state>{il_whitespace}		/* Eat any whitespace */
  1181 
  1230 
  1182 	/* The comments */
  1231 	/* The comments */
  1183 <body_state,vardecl_list_state>{comment_beg}		yy_push_state(comment_state);
  1232 <get_pou_name_state,ignore_pou_state,body_state,vardecl_list_state>{comment_beg}		yy_push_state(comment_state);
  1184 {comment_beg}						yy_push_state(comment_state);
  1233 {comment_beg}						yy_push_state(comment_state);
  1185 <comment_state>{
  1234 <comment_state>{
  1186 {comment_beg}						{if (get_opt_nested_comments()) yy_push_state(comment_state);}
  1235 {comment_beg}						{if (get_opt_nested_comments()) yy_push_state(comment_state);}
  1187 {comment_end}						yy_pop_state();
  1236 {comment_end}						yy_pop_state();
  1188 .							/* Ignore text inside comment! */
  1237 .							/* Ignore text inside comment! */