169 #endif |
169 #endif |
170 |
170 |
171 |
171 |
172 /* Function only called from within flex, but defined |
172 /* Function only called from within flex, but defined |
173 * in iec.y! |
173 * in iec.y! |
174 * We delcare it here... |
174 * We declare it here... |
175 * |
175 * |
176 * Search for a symbol in either of the two symbol tables |
176 * Search for a symbol in either of the two symbol tables |
177 * and return the token id of the first symbol found. |
177 * and return the token id of the first symbol found. |
178 * Searches first in the variables, and only if not found |
178 * Searches first in the variables, and only if not found |
179 * does it continue searching in the library elements |
179 * does it continue searching in the library elements |
180 */ |
180 */ |
181 //token_id_t get_identifier_token(const char *identifier_str); |
181 //token_id_t get_identifier_token(const char *identifier_str); |
182 int get_identifier_token(const char *identifier_str); |
182 int get_identifier_token(const char *identifier_str); |
|
183 %} |
|
184 |
|
185 |
|
186 /*********************************************/ |
|
187 /* Change parse state to body definitions... */ |
|
188 /*********************************************/ |
|
189 |
|
190 %{ |
|
191 static int goto_body_state__ = 0; |
|
192 |
|
193 void cmd_goto_body_state(void) {goto_body_state__ = 1;} |
|
194 int get_goto_body_state(void) {return goto_body_state__;} |
|
195 void rst_goto_body_state(void) {goto_body_state__ = 0;} |
183 %} |
196 %} |
184 |
197 |
185 |
198 |
186 /***************************************************/ |
199 /***************************************************/ |
187 /* Forward Declaration of functions defined later. */ |
200 /* Forward Declaration of functions defined later. */ |
268 * to make it easier to remove them later on if need be. |
281 * to make it easier to remove them later on if need be. |
269 * The body state returns any matched text back to the buffer with unput(), |
282 * The body state returns any matched text back to the buffer with unput(), |
270 * to be later matched correctly by the apropriate language parser (st or il). |
283 * to be later matched correctly by the apropriate language parser (st or il). |
271 * The state machine has 6 possible states (INITIAL, config, decl, body, st, il) |
284 * The state machine has 6 possible states (INITIAL, config, decl, body, st, il) |
272 * Possible state changes are: |
285 * Possible state changes are: |
273 * INITIAL -> decl (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
286 * INITIAL -> decl_state (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
274 * and followed by a VAR declaration) |
287 * and followed by a VAR declaration) |
275 * INITIAL -> body (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
288 * INITIAL -> il_st_state (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found, |
276 * and _not_ followed by a VAR declaration) |
289 * and _not_ followed by a VAR declaration) |
277 * INITIAL -> config (when a CONFIGURATION is found) |
290 * INITIAL -> config_state (when a CONFIGURATION is found) |
278 * decl -> body (when the last END_VAR is found, i.e. the function body starts) |
291 * decl_state -> il_st_state (when the last END_VAR is found, i.e. the function body starts) |
279 * body -> sfc (when it figures out it is parsing sfc language) |
292 * il_st_state -> sfc_state (when it figures out it is parsing sfc language) |
280 * body -> st (when it figures out it is parsing st language) |
293 * il_st_state -> st_state (when it figures out it is parsing st language) |
281 * body -> il (when it figures out it is parsing il language) |
294 * il_st_state -> il_state (when it figures out it is parsing il language) |
282 * decl -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
295 * decl_state -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
283 * st -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
296 * st_state -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
284 * sfc -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
297 * sfc_state -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
285 * il -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
298 * il_state -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found) |
286 * config -> INITIAL (when a END_CONFIGURATION is found) |
299 * config_state -> INITIAL (when a END_CONFIGURATION is found) |
287 */ |
300 */ |
288 /* we are parsing a configuration. */ |
301 /* we are parsing a configuration. */ |
289 %s config |
302 %s config_state |
290 |
303 |
291 /* we are parsing a function, program or function block declaration */ |
304 /* we are parsing a function, program or function block declaration */ |
292 %s decl |
305 %s decl_state |
293 |
306 |
294 /* we will be parsing a function body. Whether il/st is remains unknown */ |
307 /* we will be parsing a function body. Whether il/st is remains unknown */ |
295 %x body |
308 %x il_st_state |
296 |
309 |
297 /* we are parsing il code -> flex must return the EOL tokens! */ |
310 /* we are parsing il code -> flex must return the EOL tokens! */ |
298 %s il |
311 %s il_state |
299 |
312 |
300 /* we are parsing st code -> flex must not return the EOL tokens! */ |
313 /* we are parsing st code -> flex must not return the EOL tokens! */ |
301 %s st |
314 %s st_state |
302 |
315 |
303 /* we are parsing sfc code -> flex must not return the EOL tokens! */ |
316 /* we are parsing sfc code -> flex must not return the EOL tokens! */ |
304 %s sfc |
317 %s sfc_state |
305 |
318 |
306 |
319 |
307 |
320 |
308 /*******************/ |
321 /*******************/ |
309 /* File #include's */ |
322 /* File #include's */ |
708 |
726 |
709 /*********************************/ |
727 /*********************************/ |
710 /* Handle all the state changes! */ |
728 /* Handle all the state changes! */ |
711 /*********************************/ |
729 /*********************************/ |
712 |
730 |
713 /* INITIAL -> decl */ |
731 /* INITIAL -> decl_state */ |
714 <INITIAL>{ |
732 <INITIAL>{ |
715 /* NOTE: how about functions that do not delcare variables, and go directly to the body??? |
733 /* NOTE: how about functions that do not declare variables, and go directly to the il_st_state??? |
716 * - According to Section 2.5.1.3 (Function Declaration), item 2 in the list, a FUNCTION |
734 * - According to Section 2.5.1.3 (Function Declaration), item 2 in the list, a FUNCTION |
717 * must have at least one input argument, so a correct declaration will have at least |
735 * must have at least one input argument, so a correct declaration will have at least |
718 * one VAR_INPUT ... VAR_END construct! |
736 * one VAR_INPUT ... VAR_END construct! |
719 * - According to Section 2.5.2.2 (Function Block Declaration), a FUNCTION_BLOCK |
737 * - According to Section 2.5.2.2 (Function Block Declaration), a FUNCTION_BLOCK |
720 * must have at least one input argument, so a correct declaration will have at least |
738 * must have at least one input argument, so a correct declaration will have at least |
722 * - According to Section 2.5.3 (Programs), a PROGRAM must have at least one input |
740 * - According to Section 2.5.3 (Programs), a PROGRAM must have at least one input |
723 * argument, so a correct declaration will have at least one VAR_INPUT ... VAR_END |
741 * argument, so a correct declaration will have at least one VAR_INPUT ... VAR_END |
724 * construct! |
742 * construct! |
725 * |
743 * |
726 * All the above means that we needn't worry about PROGRAMs, FUNCTIONs or |
744 * All the above means that we needn't worry about PROGRAMs, FUNCTIONs or |
727 * FUNCTION_BLOCKs that do not have at least one VAR_END before the body. |
745 * FUNCTION_BLOCKs that do not have at least one VAR_END before the il_st_state. |
728 * If the code has an error, and no VAR_END before the body, we will simply |
746 * If the code has an error, and no VAR_END before the body, we will simply |
729 * continue in the <decl> state, untill the end of the FUNCTION, FUNCTION_BLOCK |
747 * continue in the <decl_state> state, untill the end of the FUNCTION, FUNCTION_BLOCK |
730 * or PROGAM. |
748 * or PROGAM. |
731 */ |
749 */ |
732 FUNCTION BEGIN(decl); return FUNCTION; |
750 FUNCTION BEGIN(decl_state); return FUNCTION; |
733 FUNCTION_BLOCK BEGIN(decl); return FUNCTION_BLOCK; |
751 FUNCTION_BLOCK BEGIN(decl_state); return FUNCTION_BLOCK; |
734 PROGRAM BEGIN(decl); return PROGRAM; |
752 PROGRAM BEGIN(decl_state); return PROGRAM; |
735 CONFIGURATION BEGIN(config); return CONFIGURATION; |
753 CONFIGURATION BEGIN(config_state); return CONFIGURATION; |
736 } |
754 } |
737 |
755 |
738 /* INITIAL -> body */ |
756 /* INITIAL -> il_st_state */ |
739 /* required if the function, program, etc.. has no VAR block! */ |
757 /* required if the function, program, etc.. has no VAR block! */ |
740 <INITIAL>{ |
758 <INITIAL>{ |
741 FUNCTION BEGIN(body); return FUNCTION; |
759 FUNCTION BEGIN(il_st_state); return FUNCTION; |
742 FUNCTION_BLOCK BEGIN(body); return FUNCTION_BLOCK; |
760 FUNCTION_BLOCK BEGIN(il_st_state); return FUNCTION_BLOCK; |
743 PROGRAM BEGIN(body); return PROGRAM; |
761 PROGRAM BEGIN(il_st_state); return PROGRAM; |
744 } |
762 } |
745 |
763 |
746 /* decl -> body */ |
764 /* decl_state -> il_st_state */ |
747 <decl>{ |
765 <decl_state>{ |
748 END_VAR{st_whitespace}VAR unput_text(strlen("END_VAR")); return END_VAR; |
766 END_VAR{st_whitespace}VAR unput_text(strlen("END_VAR")); return END_VAR; |
749 END_VAR{st_whitespace} unput_text(strlen("END_VAR")); BEGIN(body); return END_VAR; |
767 END_VAR{st_whitespace} unput_text(strlen("END_VAR")); BEGIN(il_st_state); return END_VAR; |
750 } |
768 } |
751 |
769 |
752 /* body -> (il | st | sfc) */ |
770 /* il_st_state -> (il_state | st_state | sfc_state) */ |
753 <body>INITIAL_STEP unput_text(0); BEGIN(sfc); |
771 <il_st_state>{ |
754 |
772 INITIAL_STEP unput_text(0); BEGIN(sfc_state); |
755 <body>{ |
773 {qualified_identifier}{st_whitespace}":=" unput_text(0); BEGIN(st_state); |
756 {qualified_identifier}{st_whitespace}":=" unput_text(0); BEGIN(st); |
774 {qualified_identifier}"[" unput_text(0); BEGIN(st_state); |
757 {qualified_identifier}"[" unput_text(0); BEGIN(st); |
775 |
758 |
776 RETURN unput_text(0); BEGIN(st_state); |
759 RETURN unput_text(0); BEGIN(st); |
777 IF unput_text(0); BEGIN(st_state); |
760 IF unput_text(0); BEGIN(st); |
778 CASE unput_text(0); BEGIN(st_state); |
761 CASE unput_text(0); BEGIN(st); |
779 FOR unput_text(0); BEGIN(st_state); |
762 FOR unput_text(0); BEGIN(st); |
780 WHILE unput_text(0); BEGIN(st_state); |
763 WHILE unput_text(0); BEGIN(st); |
781 REPEAT unput_text(0); BEGIN(st_state); |
764 REPEAT unput_text(0); BEGIN(st); |
782 EXIT unput_text(0); BEGIN(st_state); |
765 EXIT unput_text(0); BEGIN(st); |
783 := unput_text(0); BEGIN(st_state); /* occurs only in transitions, and not FB bodies! */ |
|
784 |
766 |
785 |
767 |
786 |
768 {identifier} {int token = get_identifier_token(yytext); |
787 {identifier} {int token = get_identifier_token(yytext); |
769 if (token == prev_declared_fb_name_token) { |
788 if (token == prev_declared_fb_name_token) { |
770 /* the code has a call to a function block */ |
789 /* the code has a call to a function block */ |
771 BEGIN(st); |
790 BEGIN(st_state); |
772 } else { |
791 } else { |
773 BEGIN(il); |
792 BEGIN(il_state); |
774 } |
793 } |
775 unput_text(0); |
794 unput_text(0); |
776 } |
795 } |
777 . unput_text(0); BEGIN(il); |
796 . unput_text(0); BEGIN(il_state); |
778 |
797 |
779 } /* end of body lexical parser */ |
798 } /* end of il_st_state lexical parser */ |
780 |
799 |
781 /* (decl | body | il | st | sfc) -> INITIAL */ |
800 /* (il_state | st_state) -> $previous_state (decl_state or sfc_state) */ |
|
801 <il_state,st_state>{ |
|
802 END_FUNCTION yy_pop_state(); unput_text(0); |
|
803 END_FUNCTION_BLOCK yy_pop_state(); unput_text(0); |
|
804 END_PROGRAM yy_pop_state(); unput_text(0); |
|
805 END_TRANSITION yy_pop_state(); unput_text(0); |
|
806 END_ACTION yy_pop_state(); unput_text(0); |
|
807 } |
|
808 |
|
809 /* (decl_state | sfc_state) -> INITIAL */ |
|
810 <decl_state,sfc_state>{ |
782 END_FUNCTION BEGIN(INITIAL); return END_FUNCTION; |
811 END_FUNCTION BEGIN(INITIAL); return END_FUNCTION; |
783 END_FUNCTION_BLOCK BEGIN(INITIAL); return END_FUNCTION_BLOCK; |
812 END_FUNCTION_BLOCK BEGIN(INITIAL); return END_FUNCTION_BLOCK; |
784 END_PROGRAM BEGIN(INITIAL); return END_PROGRAM; |
813 END_PROGRAM BEGIN(INITIAL); return END_PROGRAM; |
785 |
814 } |
786 /* config -> INITIAL */ |
815 /* config -> INITIAL */ |
787 END_CONFIGURATION BEGIN(INITIAL); return END_CONFIGURATION; |
816 END_CONFIGURATION BEGIN(INITIAL); return END_CONFIGURATION; |
788 |
817 |
789 |
818 |
790 |
819 |
791 /***************************************/ |
820 /***************************************/ |
792 /* Next is to to remove all whitespace */ |
821 /* Next is to to remove all whitespace */ |
793 /***************************************/ |
822 /***************************************/ |
794 /* NOTE: pragmas are handled right at the beginning... */ |
823 /* NOTE: pragmas are handled right at the beginning... */ |
795 |
824 |
796 <INITIAL,config,decl,st,sfc,body>{st_whitespace_no_pragma} /* Eat any whitespace */ |
825 <INITIAL,config_state,decl_state,st_state,sfc_state,il_st_state>{st_whitespace_no_pragma} /* Eat any whitespace */ |
797 <il,body>{il_whitespace_no_pragma} /* Eat any whitespace */ |
826 <il_state,il_st_state>{il_whitespace_no_pragma} /* Eat any whitespace */ |
798 |
827 |
799 |
828 |
800 /*****************************************/ |
829 /*****************************************/ |
801 /* B.1.1 Letters, digits and identifiers */ |
830 /* B.1.1 Letters, digits and identifiers */ |
802 /*****************************************/ |
831 /*****************************************/ |