stage1_2/iec_flex.ll
changeset 868 23f271534a7c
parent 867 a435684a5223
child 869 d88f47549408
equal deleted inserted replaced
867:a435684a5223 868:23f271534a7c
   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  * There is a main state machine (
   359  * There is a main state machine...
   360  *    +------> INITIAL <-------> config
   360  * 
   361  *    |           \
   361  *       +---> INITIAL <-------> config
   362  *    |           V
   362  *       |        \
   363  *    |     header_state
   363  *       |        V
   364  *    |           |
   364  *       |   header_state
   365  *    |           V
   365  *       |        |
   366  *    |  vardecl_list_state <------> var_decl
   366  *       |        V
   367  *    |           | 
   367  *     vardecl_list_state <------> var_decl
   368  *    |           V
   368  *       ^        | 
   369  *    +----------body, 
   369  *       |        | [using push()]
   370  *                ^
   370  *       |        |
   371  *                | 
   371  *       |        V
   372  *    -----------------------
   372  *       |       body, 
   373  *    |           |         |
   373  *       |        |
   374  *    v           v         v
   374  *       |        | 
   375  *   st          il       sfc
   375  *       |   -------------------
       
   376  *       |   |       |         |
       
   377  *       |   v       v         v
       
   378  *       |  st      il        sfc
       
   379  *       |   |       |         |  [using pop() when leaving st/il/sfc => goes to vardecl_list_state]
       
   380  *       |   |       |         |
       
   381  *       -----------------------
       
   382  *
       
   383  * NOTE:- When inside sfc, and an action or transition in ST/IL is found, then 
       
   384  *        we also push() to the body state. This means that sometimes, when pop()ing
       
   385  *        from st and il, the state machine may return to the sfc state!
       
   386  *      - The transitions form sfc to body will be decided by bison, which will
       
   387  *        tell flex to do the transition by calling cmd_goto_body_state().
       
   388  *   
   376  * 
   389  * 
   377  * Possible state changes are:
   390  * Possible state changes are:
   378  *   INITIAL -> goto(config_state)
   391  *   INITIAL -> goto(config_state)
   379  *                (when a CONFIGURATION is found)
   392  *                (when a CONFIGURATION is found)
   380  * 
   393  * 
   386  *  vardecl_list_state -> push current state (vardecl_list_state), and goto(vardecl_state) 
   399  *  vardecl_list_state -> push current state (vardecl_list_state), and goto(vardecl_state) 
   387  *                (when a VAR token is found)
   400  *                (when a VAR token is found)
   388  *   vardecl_state -> pop() to (vardecl_list_state) 
   401  *   vardecl_state -> pop() to (vardecl_list_state) 
   389  *                (when a END_VAR token is found)
   402  *                (when a END_VAR token is found)
   390  * 
   403  * 
   391  *   vardecl_list_state -> goto(body_state) 
   404  *   vardecl_list_state -> push current state (vardecl_list_state), and goto(body_state) 
   392  *                (when the last END_VAR is found!)
   405  *                (when the last END_VAR is found!)
   393  *
   406  *
   394  *   body_state    -> push current state(body_state); goto(sfc_state)
   407  *   body_state    -> goto(sfc_state)
   395  *                     (when it figures out it is parsing sfc language)
   408  *                     (when it figures out it is parsing sfc language)
   396  *   body_state    -> push current state(body_state); goto(st_state)
   409  *   body_state    -> goto(st_state)
   397  *                     (when it figures out it is parsing st language)
   410  *                     (when it figures out it is parsing st language)
   398  *   body_state    -> push current state(body_state); goto(il_state)
   411  *   body_state    -> goto(il_state)
   399  *                     (when it figures out it is parsing il language)
   412  *                     (when it figures out it is parsing il language)
   400  *   st_state      -> pop() to body_sate
   413  *   st_state      -> pop() to vardecl_list_state
   401  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   414  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   402  *                      END_ACTION or END_TRANSITION is found)
   415  *                      END_ACTION or END_TRANSITION is found)
   403  *   il_state      -> pop() to body_sate
   416  *   il_state      -> pop() to vardecl_list_state
   404  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   417  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   405  *                      END_ACTION or END_TRANSITION is found)
   418  *                      END_ACTION or END_TRANSITION is found)
   406  *   sfc_state     -> pop() to body_sate
   419  *   sfc_state     -> pop() to vardecl_list_state
   407  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   420  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   408  * 
   421  * 
   409  *   body_sate -> goto(INITIAL)
   422  *   vardecl_list_state -> goto(INITIAL)
   410  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   423  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
   411  *   config_state  -> goto(INITIAL)
   424  *   config_state  -> goto(INITIAL)
   412  *                     (when a END_CONFIGURATION is found)
   425  *                     (when a END_CONFIGURATION is found)
   413  * 
   426  * 
   414  *  
   427  *  
   439  * are not keywords.
   452  * are not keywords.
   440  */
   453  */
   441 %s task_init_state
   454 %s task_init_state
   442 
   455 
   443 /* we are looking for the first VAR inside a function's, program's or function block's declaration */
   456 /* we are looking for the first VAR inside a function's, program's or function block's declaration */
       
   457 /* This is not exclusive (%x) as we must be able to parse the identifier and data types of a function/FB */
   444 %s header_state
   458 %s header_state
   445 
   459 
   446 /* we are parsing a function, program or function block sequence of VAR..END_VAR delcarations */
   460 /* we are parsing a function, program or function block sequence of VAR..END_VAR delcarations */
   447 %x vardecl_list_state 
   461 %x vardecl_list_state 
   448 /* a substate of the vardecl_list_state: we are inside a specific VAR .. END_VAR */
   462 /* a substate of the vardecl_list_state: we are inside a specific VAR .. END_VAR */
   449 %s vardecl_state
   463 %s vardecl_state
   450 
   464 
   451 /* we will be parsing a function body. Whether il/st/sfc remains to be determined */
   465 /* we will be parsing a function body/action/transition. Whether il/st/sfc remains to be determined */
   452 %x body_state
   466 %x body_state
   453 
   467 
   454 /* we are parsing il code -> flex must return the EOL tokens!       */
   468 /* we are parsing il code -> flex must return the EOL tokens!       */
   455 %s il_state
   469 %s il_state
   456 
   470 
   557 enable_code_generation_pragma	"{enable code generation}"
   571 enable_code_generation_pragma	"{enable code generation}"
   558 
   572 
   559 
   573 
   560 /* Any other pragma... */
   574 /* Any other pragma... */
   561 pragma "{"[^}]*"}"|"{{"([^}]|"}"[^}])*"}}"
   575 pragma "{"[^}]*"}"|"{{"([^}]|"}"[^}])*"}}"
   562 /*
   576 
   563 pragma "{"[^}]*"}"
   577 
   564 */
       
   565 
   578 
   566 /* COMMENTS */
   579 /* COMMENTS */
   567 /* ======== */
   580 /* ======== */
   568 
   581 
   569 /* In order to allow nested comments, comments are handled by a specific comment_state state */
   582 /* In order to allow nested comments, comments are handled by a specific comment_state state */
   796  *       days         ::= fixed_point 'd' | integer 'd' ['_'] hours
   809  *       days         ::= fixed_point 'd' | integer 'd' ['_'] hours
   797  *       hours        ::= fixed_point 'h' | integer 'h' ['_'] minutes
   810  *       hours        ::= fixed_point 'h' | integer 'h' ['_'] minutes
   798  *       minutes      ::= fixed_point 'm' | integer 'm' ['_'] seconds
   811  *       minutes      ::= fixed_point 'm' | integer 'm' ['_'] seconds
   799  *       seconds      ::= fixed_point 's' | integer 's' ['_'] milliseconds
   812  *       seconds      ::= fixed_point 's' | integer 's' ['_'] milliseconds
   800  *       milliseconds ::= fixed_point 'ms'
   813  *       milliseconds ::= fixed_point 'ms'
   801 
       
   802  */
   814  */
   803 
   815 
   804 interval_ms_X		({integer_0_999}(\.{integer})?)ms
   816 interval_ms_X		({integer_0_999}(\.{integer})?)ms
   805 interval_s_X		{integer_0_59}s(_?{interval_ms_X})?|({integer_0_59}(\.{integer})?s)
   817 interval_s_X		{integer_0_59}s(_?{interval_ms_X})?|({integer_0_59}(\.{integer})?s)
   806 interval_m_X		{integer_0_59}m(_?{interval_s_X})?|({integer_0_59}(\.{integer})?m)
   818 interval_m_X		{integer_0_59}m(_?{interval_s_X})?|({integer_0_59}(\.{integer})?m)
   922 <body_state,vardecl_list_state>{enable_code_generation_pragma}    return enable_code_generation_pragma_token;
   934 <body_state,vardecl_list_state>{enable_code_generation_pragma}    return enable_code_generation_pragma_token;
   923 
   935 
   924 	/* Any other pragma we find, we just pass it up to the syntax parser...   */
   936 	/* Any other pragma we find, we just pass it up to the syntax parser...   */
   925 	/* Note that the <body_state> state is exclusive, so we have to include it here too. */
   937 	/* Note that the <body_state> state is exclusive, so we have to include it here too. */
   926 {pragma}	{/* return the pragmma without the enclosing '{' and '}' */
   938 {pragma}	{/* return the pragmma without the enclosing '{' and '}' */
   927          int cut = yytext[1]=='{'?2:1;
   939 		 int cut = yytext[1]=='{'?2:1;
   928 		 yytext[strlen(yytext)-cut] = '\0';
   940 		 yytext[strlen(yytext)-cut] = '\0';
   929 		 yylval.ID=strdup(yytext+cut);
   941 		 yylval.ID=strdup(yytext+cut);
   930 		 return pragma_token;
   942 		 return pragma_token;
   931 		}
   943 		}
   932 <body_state,vardecl_list_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */
   944 <body_state,vardecl_list_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */
  1032 	 *       FUNCTION_BLOCKs that do not have at least one VAR_END before the body_state.
  1044 	 *       FUNCTION_BLOCKs that do not have at least one VAR_END before the body_state.
  1033 	 *       If the code has an error, and no VAR_END before the body, we will simply
  1045 	 *       If the code has an error, and no VAR_END before the body, we will simply
  1034 	 *       continue in the <vardecl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK
  1046 	 *       continue in the <vardecl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK
  1035 	 *       or PROGAM.
  1047 	 *       or PROGAM.
  1036 	 */
  1048 	 */
  1037 FUNCTION				BEGIN(header_state); return FUNCTION;
  1049 FUNCTION				yy_push_state(header_state); return FUNCTION;
  1038 FUNCTION_BLOCK				BEGIN(header_state); return FUNCTION_BLOCK;
  1050 FUNCTION_BLOCK				yy_push_state(header_state); return FUNCTION_BLOCK;
  1039 PROGRAM					BEGIN(header_state); return PROGRAM;
  1051 PROGRAM					yy_push_state(header_state); return PROGRAM;
  1040 CONFIGURATION				BEGIN(config_state); return CONFIGURATION;
  1052 CONFIGURATION				BEGIN(config_state); return CONFIGURATION;
  1041 }
  1053 }
  1042 
  1054 
  1043 	/* INITIAL -> body_state */
  1055 	/* INITIAL -> body_state */
  1044 	/* required if the function, program, etc.. has no VAR block! */
  1056 	/* required if the function, program, etc.. has no VAR block! */
  1052 FUNCTION_BLOCK	BEGIN(body_state); return FUNCTION_BLOCK;
  1064 FUNCTION_BLOCK	BEGIN(body_state); return FUNCTION_BLOCK;
  1053 PROGRAM		BEGIN(body_state); return PROGRAM;
  1065 PROGRAM		BEGIN(body_state); return PROGRAM;
  1054 }
  1066 }
  1055 	*/
  1067 	*/
  1056 
  1068 
  1057 	/* header_state -> (vardecl_state | body_state) */
  1069 	/* header_state -> (vardecl_list_state) */
  1058 <header_state>{
  1070 <header_state>{
  1059 VAR				unput_text(0); BEGIN(vardecl_list_state);
  1071 VAR				| /* execute the next rule's action, i.e. fall-through! */
  1060 }
  1072 VAR_INPUT			|
  1061 
  1073 VAR_OUTPUT			|
  1062 
  1074 VAR_IN_OUT			|
       
  1075 VAR_EXTERNAL			|
       
  1076 VAR_GLOBAL			|
       
  1077 VAR_TEMP			|
       
  1078 VAR_CONFIG			|
       
  1079 VAR_ACCESS			unput_text(0); BEGIN(vardecl_list_state);
       
  1080 }
       
  1081 
       
  1082 
       
  1083 	/* vardecl_list_state -> (vardecl_state | body_state | INITIAL) */
  1063 <vardecl_list_state>{
  1084 <vardecl_list_state>{
       
  1085 VAR_INPUT			| /* execute the next rule's action, i.e. fall-through! */
       
  1086 VAR_OUTPUT			|
       
  1087 VAR_IN_OUT			|
       
  1088 VAR_EXTERNAL			|
       
  1089 VAR_GLOBAL			|
       
  1090 VAR_TEMP			|
       
  1091 VAR_CONFIG			|
       
  1092 VAR_ACCESS			|
  1064 VAR				unput_text(0); yy_push_state(vardecl_state);
  1093 VAR				unput_text(0); yy_push_state(vardecl_state);
  1065 .				unput_text(0); BEGIN(body_state); /* anything else, just change to body_state! */
  1094 
  1066 }
  1095 END_FUNCTION			unput_text(0); BEGIN(INITIAL); 
  1067 
  1096 END_FUNCTION_BLOCK		unput_text(0); BEGIN(INITIAL); 
  1068 
  1097 END_PROGRAM			unput_text(0); BEGIN(INITIAL); 
       
  1098 
       
  1099 .				unput_text(0); yy_push_state(body_state); /* anything else, just change to body_state! */
       
  1100 }
       
  1101 
       
  1102 
       
  1103 	/* vardecl_list_state -> pop to $previous_state (vardecl_list_state) */
  1069 <vardecl_state>{
  1104 <vardecl_state>{
  1070 END_VAR				yy_pop_state(); return END_VAR; /* pop back to header_state */
  1105 END_VAR				yy_pop_state(); return END_VAR; /* pop back to header_state */
  1071 }
  1106 }
  1072 
  1107 
  1073 
  1108 
  1074 	/* body_state -> (il_state | st_state) */
  1109 	/* body_state -> (il_state | st_state | sfc_state) */
  1075 <body_state>{
  1110 <body_state>{
  1076 END_FUNCTION			BEGIN(INITIAL); return END_FUNCTION;
  1111 INITIAL_STEP			unput_text(0); BEGIN(sfc_state); 
  1077 END_FUNCTION_BLOCK		BEGIN(INITIAL); return END_FUNCTION_BLOCK;
  1112 
  1078 END_PROGRAM			BEGIN(INITIAL); return END_PROGRAM;
  1113 {qualified_identifier}		unput_text(0); BEGIN(st_state); /* will always be followed by '[' for an array access, or ':=' as the left hand of an assignment statement */
  1079 
  1114 {direct_variable_standard}	unput_text(0); BEGIN(st_state); /* will always be followed by ':=' as the left hand of an assignment statement */
  1080 INITIAL_STEP			unput_text(0); yy_push_state(sfc_state); 
  1115 
  1081 
  1116 RETURN				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 */
  1117 IF				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 */
  1118 CASE				unput_text(0); BEGIN(st_state);
  1084 
  1119 FOR				unput_text(0); BEGIN(st_state);
  1085 RETURN				unput_text(0); yy_push_state(st_state);
  1120 WHILE				unput_text(0); BEGIN(st_state);
  1086 IF				unput_text(0); yy_push_state(st_state);
  1121 EXIT				unput_text(0); BEGIN(st_state);
  1087 CASE				unput_text(0); yy_push_state(st_state);
  1122 REPEAT				unput_text(0); BEGIN(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);
       
  1092 
  1123 
  1093 	/* ':=' occurs only in transitions, and not Function or FB bodies! */
  1124 	/* ':=' occurs only in transitions, and not Function or FB bodies! */
  1094 :=				unput_text(0); yy_push_state(st_state);
  1125 :=				unput_text(0); BEGIN(st_state);
  1095 
  1126 
  1096 {identifier}	{int token = get_identifier_token(yytext);
  1127 {identifier}	{int token = get_identifier_token(yytext);
  1097 		 if ((token == prev_declared_fb_name_token) || (token == prev_declared_variable_name_token)) {
  1128 		 if ((token == prev_declared_fb_name_token) || (token == prev_declared_variable_name_token)) {
  1098 		   /* the code has a call to a function block OR has an assingment with a variable as the lvalue */
  1129 		   /* the code has a call to a function block OR has an assingment with a variable as the lvalue */
  1099 		   unput_text(0); yy_push_state(st_state);
  1130 		   unput_text(0); BEGIN(st_state);
  1100 		 } else
  1131 		 } else
  1101  		 if (token == prev_declared_derived_function_name_token) {
  1132  		 if (token == prev_declared_derived_function_name_token) {
  1102 		   /* the code has a call to a function - must be IL */
  1133 		   /* the code has a call to a function - must be IL */
  1103 		   unput_text(0); yy_push_state(il_state);
  1134 		   unput_text(0); BEGIN(il_state);
  1104 		 } else {
  1135 		 } else {
  1105 		   /* Might be a lable in IL, or a bug in ST/IL code. We jump to IL */
  1136 		   /* 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);
  1137 		   unput_text(0); BEGIN(il_state);
  1107 		 }
  1138 		 }
  1108 		}
  1139 		}
  1109 
  1140 
  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... */
  1141 .		unput_text(0); BEGIN(il_state); /* Don't know what it could be. This is most likely a bug. Let's just to a random state... */
  1111 }	/* end of body_state lexical parser */
  1142 }	/* end of body_state lexical parser */
  1112 
  1143 
  1113 
  1144 
  1114 
  1145 
  1115 	/* (il_state | st_state) -> $previous_state (vardecl_state or sfc_state) */
  1146 	/* (il_state | st_state) -> pop to $previous_state (vardecl_list_state or sfc_state) */
  1116 <il_state,st_state>{
  1147 <il_state,st_state>{
  1117 END_FUNCTION		yy_pop_state(); unput_text(0);
  1148 END_FUNCTION		yy_pop_state(); unput_text(0);
  1118 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1149 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1119 END_PROGRAM		yy_pop_state(); unput_text(0);
  1150 END_PROGRAM		yy_pop_state(); unput_text(0);
  1120 END_TRANSITION		yy_pop_state(); unput_text(0);
  1151 END_TRANSITION		yy_pop_state(); unput_text(0);
  1121 END_ACTION		yy_pop_state(); unput_text(0);
  1152 END_ACTION		yy_pop_state(); unput_text(0);
  1122 }
  1153 }
  1123 
  1154 
  1124 	/* sfc_state -> INITIAL */
  1155 	/* sfc_state -> pop to $previous_state (vardecl_list_state or sfc_state) */
  1125 <sfc_state>{
  1156 <sfc_state>{
  1126 END_FUNCTION		yy_pop_state(); unput_text(0);
  1157 END_FUNCTION		yy_pop_state(); unput_text(0);
  1127 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1158 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1128 END_PROGRAM		yy_pop_state(); unput_text(0);
  1159 END_PROGRAM		yy_pop_state(); unput_text(0);
  1129 }
  1160 }