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 * |
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 } |