266 * not easily distinguish between il and st code, since function |
266 * not easily distinguish between il and st code, since function |
267 * calls in il are very similar to function block calls in st. |
267 * calls in il are very similar to function block calls in st. |
268 * We therefore use an extra 'body' state. When the lexical parser |
268 * We therefore use an extra 'body' state. When the lexical parser |
269 * finds that last END_VAR, it enters the body state. This state |
269 * finds that last END_VAR, it enters the body state. This state |
270 * must figure out what language is being parsed from the first few |
270 * must figure out what language is being parsed from the first few |
271 * tokens, and switch to the correct state (st or il) according to the |
271 * tokens, and switch to the correct state (st, il or sfc) according to the |
272 * language. This means that we insert quite a bit of knowledge of the |
272 * language. This means that we insert quite a bit of knowledge of the |
273 * syntax of the languages into the lexical parser. This is ugly, but it |
273 * syntax of the languages into the lexical parser. This is ugly, but it |
274 * works, and at least it is possible to keep all the state changes together |
274 * works, and at least it is possible to keep all the state changes together |
275 * to make it easier to remove them later on if need be. |
275 * to make it easier to remove them later on if need be. |
276 * The body state returns any matched text back to the buffer with unput(), |
276 * Once the language being parsed has been identified, |
277 * to be later matched correctly by the apropriate language parser (st or il). |
277 * the body state returns any matched text back to the buffer with unput(), |
278 * The state machine has 6 possible states (INITIAL, config, decl, body, st, il) |
278 * to be later matched correctly by the apropriate language parser (st, il or sfc). |
|
279 * |
|
280 * Aditionally, in sfc state it may further recursively enter the body state |
|
281 * once again. This is because an sfc body may contain ACTIONS, which are then |
|
282 * written in one of the three languages (ST, IL or SFC), so once again we need |
|
283 * to figure out which language the ACTION in the SFC was written in. We already |
|
284 * ahve all that done in the body state, so we recursively transition to the body |
|
285 * state once again. |
|
286 * Note that in this case, when coming out of the st/il state (whichever language |
|
287 * the action was written in) the sfc state will become active again. This is done by |
|
288 * pushing and poping the previously active state! |
|
289 * |
|
290 * The sfc_qualifier_state is required because when parsing actions within an |
|
291 * sfc, we will be expecting action qualifiers (N, P, R, S, DS, SD, ...). In order |
|
292 * to bison to work correctly, these qualifiers must be returned as tokens. However, |
|
293 * these tokens are not reserved keywords, which means it should be possible to |
|
294 * define variables/functions/FBs with any of these names (including |
|
295 * S and R which are special because they are also IL operators). So, when we are not |
|
296 * expecting any action qualifiers, flex does not return these tokens, and is free |
|
297 * to interpret them as previously defined variables/functions/... as the case may be. |
|
298 * |
|
299 * The state machine has 7 possible states (INITIAL, config, decl, body, st, il, sfc) |
279 * Possible state changes are: |
300 * Possible state changes are: |
280 * INITIAL -> decl_state (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
301 * INITIAL -> goto(decl_state) |
281 * and followed by a VAR declaration) |
302 * (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
282 * INITIAL -> il_st_state (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
303 * and followed by a VAR declaration) |
283 * and _not_ followed by a VAR declaration) |
304 * INITIAL -> goto(body_state) |
284 * INITIAL -> config_state (when a CONFIGURATION is found) |
305 * (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
285 * decl_state -> il_st_state (when the last END_VAR is found, i.e. the function body starts) |
306 * and _not_ followed by a VAR declaration) |
286 * il_st_state -> sfc_state (when it figures out it is parsing sfc language) |
307 * (This transition is actually commented out, since the syntax |
287 * il_st_state -> st_state (when it figures out it is parsing st language) |
308 * does not allow the declaration of functions, FBs, or programs |
288 * il_st_state -> il_state (when it figures out it is parsing il language) |
309 * without any VAR declaration!) |
289 * decl_state -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
310 * INITIAL -> goto(config_state) |
290 * st_state -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
311 * (when a CONFIGURATION is found) |
291 * sfc_state -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
312 * decl_state -> push(decl_state); goto(body_state) |
292 * il_state -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
313 * (when the last END_VAR is found, i.e. the function body starts) |
293 * config_state -> INITIAL (when a END_CONFIGURATION is found) |
314 * decl_state -> push(decl_state); goto(sfc_state) |
294 */ |
315 * (when it figures out it is parsing sfc language) |
|
316 * body_state -> goto(st_state) |
|
317 * (when it figures out it is parsing st language) |
|
318 * body_state -> goto(il_state) |
|
319 * (when it figures out it is parsing il language) |
|
320 * st_state -> pop() |
|
321 * (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM, |
|
322 * END_ACTION or END_TRANSITION is found) |
|
323 * il_state -> pop() |
|
324 * (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM, |
|
325 * END_ACTION or END_TRANSITION is found) |
|
326 * decl_state -> goto(INITIAL) |
|
327 * (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
|
328 * sfc_state -> goto(INITIAL) |
|
329 * (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
|
330 * config_state -> goto(INITIAL) |
|
331 * (when a END_CONFIGURATION is found) |
|
332 * sfc_state -> push(sfc_state); goto(body_state) |
|
333 * (when parsing an action. This transition is requested by bison) |
|
334 * sfc_state -> push(sfc_state); goto(sfc_qualifier_state) |
|
335 * (when expecting an action qualifier. This transition is requested by bison) |
|
336 * sfc_qualifier_state -> pop() |
|
337 * (when no longer expecting an action qualifier. This transition is requested by bison) |
|
338 * |
|
339 */ |
|
340 |
|
341 |
|
342 |
295 /* we are parsing a configuration. */ |
343 /* we are parsing a configuration. */ |
296 %s config_state |
344 %s config_state |
297 |
345 |
298 /* we are parsing a function, program or function block declaration */ |
346 /* we are parsing a function, program or function block declaration */ |
299 %s decl_state |
347 %s decl_state |
300 |
348 |
301 /* we will be parsing a function body. Whether il/st is remains unknown */ |
349 /* we will be parsing a function body. Whether il/st is remains unknown */ |
302 %x il_st_state |
350 %x body_state |
303 |
351 |
304 /* we are parsing il code -> flex must return the EOL tokens! */ |
352 /* we are parsing il code -> flex must return the EOL tokens! */ |
305 %s il_state |
353 %s il_state |
306 |
354 |
307 /* we are parsing st code -> flex must not return the EOL tokens! */ |
355 /* we are parsing st code -> flex must not return the EOL tokens! */ |
308 %s st_state |
356 %s st_state |
309 |
357 |
310 /* we are parsing sfc code -> flex must not return the EOL tokens! */ |
358 /* we are parsing sfc code -> flex must not return the EOL tokens! */ |
311 %s sfc_state |
359 %s sfc_state |
312 |
360 |
|
361 /* we are parsing sfc code, and expecting an action qualifier. */ |
|
362 %s sfc_qualifier_state |
313 |
363 |
314 |
364 |
315 /*******************/ |
365 /*******************/ |
316 /* File #include's */ |
366 /* File #include's */ |
317 /*******************/ |
367 /*******************/ |
615 /***** *****/ |
665 /***** *****/ |
616 /*****************************************************/ |
666 /*****************************************************/ |
617 /*****************************************************/ |
667 /*****************************************************/ |
618 /*****************************************************/ |
668 /*****************************************************/ |
619 |
669 |
|
670 /***********************************************************/ |
|
671 /* Handle requests sent by bison for flex to change state. */ |
|
672 /***********************************************************/ |
620 if (get_goto_body_state()) { |
673 if (get_goto_body_state()) { |
621 yy_push_state(il_st_state); |
674 yy_push_state(body_state); |
622 rst_goto_body_state(); |
675 rst_goto_body_state(); |
623 } |
676 } |
624 |
677 |
625 /*********************************/ |
678 if (get_goto_sfc_qualifier_state()) { |
|
679 yy_push_state(sfc_qualifier_state); |
|
680 rst_goto_sfc_qualifier_state(); |
|
681 } |
|
682 |
|
683 if (get_pop_state()) { |
|
684 yy_pop_state(); |
|
685 rst_pop_state(); |
|
686 } |
|
687 |
|
688 |
|
689 /***************************/ |
626 /* Handle the pragmas! */ |
690 /* Handle the pragmas! */ |
627 /*********************************/ |
691 /***************************/ |
628 |
692 |
629 /* We start off by searching for the pragmas we handle in the lexical parser. */ |
693 /* We start off by searching for the pragmas we handle in the lexical parser. */ |
630 <INITIAL>{file_include_pragma} unput_text(0); yy_push_state(include_beg); |
694 <INITIAL>{file_include_pragma} unput_text(0); yy_push_state(include_beg); |
631 |
695 |
632 /* Any other pragma we find, we just pass it up to the syntax parser... */ |
696 /* Any other pragma we find, we just pass it up to the syntax parser... */ |
633 /* Note that the <il_st_state> state is exclusive, so we have to include it here too. */ |
697 /* Note that the <body_state> state is exclusive, so we have to include it here too. */ |
634 {pragma} {/* return the pragmma without the enclosing '{' and '}' */ |
698 {pragma} {/* return the pragmma without the enclosing '{' and '}' */ |
635 yytext[strlen(yytext)-1] = '\0'; |
699 yytext[strlen(yytext)-1] = '\0'; |
636 yylval.ID=strdup(yytext+1); |
700 yylval.ID=strdup(yytext+1); |
637 return pragma_token; |
701 return pragma_token; |
638 } |
702 } |
639 <il_st_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */ |
703 <body_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */ |
640 yytext[strlen(yytext)-1] = '\0'; |
704 yytext[strlen(yytext)-1] = '\0'; |
641 yylval.ID=strdup(yytext+1); |
705 yylval.ID=strdup(yytext+1); |
642 return pragma_token; |
706 return pragma_token; |
643 } |
707 } |
644 |
708 |
724 * - According to Section 2.5.3 (Programs), a PROGRAM must have at least one input |
788 * - According to Section 2.5.3 (Programs), a PROGRAM must have at least one input |
725 * argument, so a correct declaration will have at least one VAR_INPUT ... VAR_END |
789 * argument, so a correct declaration will have at least one VAR_INPUT ... VAR_END |
726 * construct! |
790 * construct! |
727 * |
791 * |
728 * All the above means that we needn't worry about PROGRAMs, FUNCTIONs or |
792 * All the above means that we needn't worry about PROGRAMs, FUNCTIONs or |
729 * FUNCTION_BLOCKs that do not have at least one VAR_END before the il_st_state. |
793 * FUNCTION_BLOCKs that do not have at least one VAR_END before the body_state. |
730 * If the code has an error, and no VAR_END before the body, we will simply |
794 * If the code has an error, and no VAR_END before the body, we will simply |
731 * continue in the <decl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK |
795 * continue in the <decl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK |
732 * or PROGAM. |
796 * or PROGAM. |
733 */ |
797 */ |
734 FUNCTION BEGIN(decl_state); return FUNCTION; |
798 FUNCTION BEGIN(decl_state); return FUNCTION; |
735 FUNCTION_BLOCK BEGIN(decl_state); return FUNCTION_BLOCK; |
799 FUNCTION_BLOCK BEGIN(decl_state); return FUNCTION_BLOCK; |
736 PROGRAM BEGIN(decl_state); return PROGRAM; |
800 PROGRAM BEGIN(decl_state); return PROGRAM; |
737 CONFIGURATION BEGIN(config_state); return CONFIGURATION; |
801 CONFIGURATION BEGIN(config_state); return CONFIGURATION; |
738 } |
802 } |
739 |
803 |
740 /* INITIAL -> il_st_state */ |
804 /* INITIAL -> body_state */ |
741 /* required if the function, program, etc.. has no VAR block! */ |
805 /* required if the function, program, etc.. has no VAR block! */ |
742 /* We comment it out since the standard does not allow this. */ |
806 /* We comment it out since the standard does not allow this. */ |
743 /* NOTE: Even if we were to include the following code, it */ |
807 /* NOTE: Even if we were to include the following code, it */ |
744 /* would have no effect whatsoever since the above */ |
808 /* would have no effect whatsoever since the above */ |
745 /* rules will take precendence! */ |
809 /* rules will take precendence! */ |
746 /* |
810 /* |
747 <INITIAL>{ |
811 <INITIAL>{ |
748 FUNCTION BEGIN(il_st_state); return FUNCTION; |
812 FUNCTION BEGIN(body_state); return FUNCTION; |
749 FUNCTION_BLOCK BEGIN(il_st_state); return FUNCTION_BLOCK; |
813 FUNCTION_BLOCK BEGIN(body_state); return FUNCTION_BLOCK; |
750 PROGRAM BEGIN(il_st_state); return PROGRAM; |
814 PROGRAM BEGIN(body_state); return PROGRAM; |
751 } |
815 } |
752 */ |
816 */ |
753 |
817 |
754 /* decl_state -> (il_st_state | sfc_state) */ |
818 /* decl_state -> (body_state | sfc_state) */ |
755 <decl_state>{ |
819 <decl_state>{ |
756 END_VAR{st_whitespace}VAR {unput_text(strlen("END_VAR")); |
820 END_VAR{st_whitespace}VAR {unput_text(strlen("END_VAR")); |
757 return END_VAR; |
821 return END_VAR; |
758 } |
822 } |
759 END_VAR{st_whitespace}INITIAL_STEP {unput_text(strlen("END_VAR")); |
823 END_VAR{st_whitespace}INITIAL_STEP {unput_text(strlen("END_VAR")); |
781 REPEAT unput_text(0); BEGIN(st_state); |
844 REPEAT unput_text(0); BEGIN(st_state); |
782 EXIT unput_text(0); BEGIN(st_state); |
845 EXIT unput_text(0); BEGIN(st_state); |
783 /* ':=' occurs only in transitions, and not Function or FB bodies! */ |
846 /* ':=' occurs only in transitions, and not Function or FB bodies! */ |
784 := unput_text(0); BEGIN(st_state); |
847 := unput_text(0); BEGIN(st_state); |
785 |
848 |
|
849 /* Hopefully, the above rules (along with the last one), |
|
850 * used to distinguish ST from IL, are |
|
851 * enough to handle all ocurrences. However, if |
|
852 * there is some situation where the compiler is getting confused, |
|
853 * we add the following rule to detect 'label:' in IL code. This will |
|
854 * allow the user to insert a label right at the beginning (which |
|
855 * will probably not be used further by his code) simply as a way |
|
856 * to force the compiler to interpret his code as IL code. |
|
857 */ |
|
858 {identifier}{st_whitespace}":"{st_whitespace} unput_text(0); BEGIN(il_state); |
786 |
859 |
787 {identifier} {int token = get_identifier_token(yytext); |
860 {identifier} {int token = get_identifier_token(yytext); |
788 if (token == prev_declared_fb_name_token) { |
861 if (token == prev_declared_fb_name_token) { |
789 /* the code has a call to a function block */ |
862 /* the code has a call to a function block */ |
|
863 /* NOTE: if we ever decide to allow the user to use IL operator tokens |
|
864 * (LD, ST, ...) as identifiers for variable names (including |
|
865 * function block instances), then the above inference/conclusion |
|
866 * may be incorrect, and this condition may have to be changed! |
|
867 */ |
790 BEGIN(st_state); |
868 BEGIN(st_state); |
791 } else { |
869 } else { |
792 BEGIN(il_state); |
870 BEGIN(il_state); |
793 } |
871 } |
794 unput_text(0); |
872 unput_text(0); |
795 } |
873 } |
|
874 |
796 . unput_text(0); BEGIN(il_state); |
875 . unput_text(0); BEGIN(il_state); |
797 } /* end of il_st_state lexical parser */ |
876 } /* end of body_state lexical parser */ |
798 |
877 |
799 /* (il_state | st_state) -> $previous_state (decl_state or sfc_state) */ |
878 /* (il_state | st_state) -> $previous_state (decl_state or sfc_state) */ |
800 <il_state,st_state>{ |
879 <il_state,st_state>{ |
801 END_FUNCTION yy_pop_state(); unput_text(0); |
880 END_FUNCTION yy_pop_state(); unput_text(0); |
802 END_FUNCTION_BLOCK yy_pop_state(); unput_text(0); |
881 END_FUNCTION_BLOCK yy_pop_state(); unput_text(0); |