stage1_2/iec_flex.ll
changeset 870 9c6c588fd708
parent 822 a7d9e0b8636b
parent 869 d88f47549408
child 881 e05d69c1ccb3
equal deleted inserted replaced
822:a7d9e0b8636b 870:9c6c588fd708
     3  *
     3  *
     4  *  Copyright (C) 2003-2011  Mario de Sousa (msousa@fe.up.pt)
     4  *  Copyright (C) 2003-2011  Mario de Sousa (msousa@fe.up.pt)
     5  *
     5  *
     6  *  This program is free software: you can redistribute it and/or modify
     6  *  This program is free software: you can redistribute it and/or modify
     7  *  it under the terms of the GNU General Public License as published by
     7  *  it under the terms of the GNU General Public License as published by
     8  *  the Free Software Foundation, either version 3 of the License, or
     8  *  the Free Software Foundation, either version 3 of thest_whitespaceLicense, or
     9  *  (at your option) any later version.
     9  *  (at your option) any later version.
    10  *
    10  *
    11  *  This program is distributed in the hope that it will be useful,
    11  *  This program is distributed in the hope that it will be useful,
    12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   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  * The state machine has 7 possible states (INITIAL, config, decl, body, st, il, sfc)
   359  * There is a main state machine...
       
   360  * 
       
   361  *       +---> INITIAL <-------> config
       
   362  *       |        \
       
   363  *       |        V
       
   364  *       |   header_state
       
   365  *       |        |
       
   366  *       |        V
       
   367  *     vardecl_list_state <------> var_decl
       
   368  *       ^        | 
       
   369  *       |        | [using push()]
       
   370  *       |        |
       
   371  *       |        V
       
   372  *       |       body, 
       
   373  *       |        |
       
   374  *       |        | 
       
   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  *   
       
   389  * 
   360  * Possible state changes are:
   390  * Possible state changes are:
   361  *   INITIAL -> goto(decl_state)
       
   362  *               (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found,
       
   363  *                and followed by a VAR declaration)
       
   364  *   INITIAL -> goto(body_state) 
       
   365  *                (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found,
       
   366  *                 and _not_ followed by a VAR declaration)
       
   367  *                (This transition is actually commented out, since the syntax
       
   368  *                 does not allow the declaration of functions, FBs, or programs
       
   369  *                 without any VAR declaration!)
       
   370  *   INITIAL -> goto(config_state)
   391  *   INITIAL -> goto(config_state)
   371  *                (when a CONFIGURATION is found)
   392  *                (when a CONFIGURATION is found)
   372  *   decl_state    -> push(decl_state); goto(body_state)
   393  * 
   373  *                     (when the last END_VAR is found, i.e. the function body starts)
   394  *   INITIAL -> goto(header_state)
   374  *   decl_state    -> push(decl_state); goto(sfc_state)
   395  *               (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found)
       
   396  *   header_state -> goto(vardecl_list_state)
       
   397  *               (When the first VAR token is found, i.e. at begining of first VAR .. END_VAR declaration)
       
   398  * 
       
   399  *  vardecl_list_state -> push current state (vardecl_list_state), and goto(vardecl_state) 
       
   400  *                (when a VAR token is found)
       
   401  *   vardecl_state -> pop() to (vardecl_list_state) 
       
   402  *                (when a END_VAR token is found)
       
   403  * 
       
   404  *   vardecl_list_state -> push current state (vardecl_list_state), and goto(body_state) 
       
   405  *                (when the last END_VAR is found!)
       
   406  *
       
   407  *   body_state    -> goto(sfc_state)
   375  *                     (when it figures out it is parsing sfc language)
   408  *                     (when it figures out it is parsing sfc language)
   376  *   body_state    -> goto(st_state)
   409  *   body_state    -> goto(st_state)
   377  *                     (when it figures out it is parsing st language)
   410  *                     (when it figures out it is parsing st language)
   378  *   body_state    -> goto(il_state)
   411  *   body_state    -> goto(il_state)
   379  *                     (when it figures out it is parsing il language)
   412  *                     (when it figures out it is parsing il language)
   380  *   st_state      -> pop()
   413  *   st_state      -> pop() to vardecl_list_state
   381  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   414  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   382  *                      END_ACTION or END_TRANSITION is found)
   415  *                      END_ACTION or END_TRANSITION is found)
   383  *   il_state      -> pop()
   416  *   il_state      -> pop() to vardecl_list_state
   384  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   417  *                     (when a END_FUNCTION, END_FUNCTION_BLOCK, END_PROGRAM,
   385  *                      END_ACTION or END_TRANSITION is found)
   418  *                      END_ACTION or END_TRANSITION is found)
   386  *   decl_state    -> goto(INITIAL)
   419  *   sfc_state     -> pop() to vardecl_list_state
   387  *                     (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)
   388  *   sfc_state     -> goto(INITIAL)
   421  * 
       
   422  *   vardecl_list_state -> goto(INITIAL)
   389  *                     (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)
   390  *   config_state  -> goto(INITIAL)
   424  *   config_state  -> goto(INITIAL)
   391  *                     (when a END_CONFIGURATION is found)
   425  *                     (when a END_CONFIGURATION is found)
   392  *   sfc_state     -> push(sfc_state); goto(body_state)
   426  * 
       
   427  *  
       
   428  *   sfc_state     -> push current state(sfc_state); goto(body_state)
   393  *                     (when parsing an action. This transition is requested by bison)
   429  *                     (when parsing an action. This transition is requested by bison)
   394  *   sfc_state     -> push(sfc_state); goto(sfc_qualifier_state)
   430  *   sfc_state     -> push current state(sfc_state); goto(sfc_qualifier_state)
   395  *                     (when expecting an action qualifier. This transition is requested by bison)
   431  *                     (when expecting an action qualifier. This transition is requested by bison)
   396  *   sfc_qualifier_state -> pop()
   432  *   sfc_qualifier_state -> pop() to sfc_state
   397  *                     (when no longer expecting an action qualifier. This transition is requested by bison)
   433  *                     (when no longer expecting an action qualifier. This transition is requested by bison)
       
   434  *
   398  *   config_state  -> push(config_state); goto(task_init_state)
   435  *   config_state  -> push(config_state); goto(task_init_state)
   399  *                     (when parsing a task initialisation. This transition is requested by bison)
   436  *                     (when parsing a task initialisation. This transition is requested by bison)
   400  *   task_init_state -> pop()
   437  *   task_init_state -> pop()
   401  *                     (when no longer parsing task initialisation parameters. This transition is requested by bison)
   438  *                     (when no longer parsing task initialisation parameters. This transition is requested by bison)
   402  *
   439  *
       
   440  * 
       
   441  * There is another secondary state machine for parsing comments, another for file_includes, 
       
   442  * and yet another for time literals.
   403  */
   443  */
   404 
   444 
   405 
   445 
   406 /* we are parsing a configuration. */
   446 /* we are parsing a configuration. */
   407 %s config_state
   447 %s config_state
   411  * tokens, and not as possible identifiers. Note that the above words
   451  * tokens, and not as possible identifiers. Note that the above words
   412  * are not keywords.
   452  * are not keywords.
   413  */
   453  */
   414 %s task_init_state
   454 %s task_init_state
   415 
   455 
   416 /* we are parsing a function, program or function block declaration */
   456 /* we are looking for the first VAR inside a function's, program's or function block's declaration */
   417 %s decl_state
   457 /* This is not exclusive (%x) as we must be able to parse the identifier and data types of a function/FB */
   418 
   458 %s header_state
   419 /* we will be parsing a function body. Whether il/st/sfc remains to be determined */
   459 
       
   460 /* we are parsing a function, program or function block sequence of VAR..END_VAR delcarations */
       
   461 %x vardecl_list_state 
       
   462 /* a substate of the vardecl_list_state: we are inside a specific VAR .. END_VAR */
       
   463 %s vardecl_state
       
   464 
       
   465 /* we will be parsing a function body/action/transition. Whether il/st/sfc remains to be determined */
   420 %x body_state
   466 %x body_state
   421 
   467 
   422 /* we are parsing il code -> flex must return the EOL tokens!       */
   468 /* we are parsing il code -> flex must return the EOL tokens!       */
   423 %s il_state
   469 %s il_state
   424 
   470 
   434 /* we are parsing sfc code, and expecting the priority token.       */
   480 /* we are parsing sfc code, and expecting the priority token.       */
   435 %s sfc_priority_state
   481 %s sfc_priority_state
   436 
   482 
   437 /* we are parsing a TIME# literal. We must not return any {identifier} tokens. */
   483 /* we are parsing a TIME# literal. We must not return any {identifier} tokens. */
   438 %x time_literal_state
   484 %x time_literal_state
       
   485 
       
   486 /* we are parsing a comment. */
       
   487 %x comment_state
   439 
   488 
   440 
   489 
   441 /*******************/
   490 /*******************/
   442 /* File #include's */
   491 /* File #include's */
   443 /*******************/
   492 /*******************/
   453 %x include_filename
   502 %x include_filename
   454 %x include_end
   503 %x include_end
   455 
   504 
   456 
   505 
   457 file_include_pragma_filename	[^\"]*
   506 file_include_pragma_filename	[^\"]*
   458 file_include_pragma_beg		"{#include"{st_whitespace_only}\"
   507 file_include_pragma_beg		"{#include"{st_whitespace}\"
   459 file_include_pragma_end		\"{st_whitespace_only}"}"
   508 file_include_pragma_end		\"{st_whitespace}"}"
   460 file_include_pragma			{file_include_pragma_beg}{file_include_pragma_filename}{file_include_pragma_end}
   509 file_include_pragma			{file_include_pragma_beg}{file_include_pragma_filename}{file_include_pragma_end}
   461 
   510 
   462 
   511 
   463 %{
   512 %{
   464 #define MAX_INCLUDE_DEPTH 16
   513 #define MAX_INCLUDE_DEPTH 16
   497 
   546 
   498 /*****************************/
   547 /*****************************/
   499 /* Prelimenary constructs... */
   548 /* Prelimenary constructs... */
   500 /*****************************/
   549 /*****************************/
   501 
   550 
       
   551 /* PRAGMAS */
       
   552 /* ======= */
   502 /* In order to allow the declaration of POU prototypes (Function, FB, Program, ...),
   553 /* In order to allow the declaration of POU prototypes (Function, FB, Program, ...),
   503  * especially the prototypes of Functions and FBs defined in the standard
   554  * especially the prototypes of Functions and FBs defined in the standard
   504  * (i.e. standard functions and FBs), we extend the IEC 61131-3 standard syntax 
   555  * (i.e. standard functions and FBs), we extend the IEC 61131-3 standard syntax 
   505  * with two pragmas to indicate that the code is to be parsed (going through the 
   556  * with two pragmas to indicate that the code is to be parsed (going through the 
   506  * lexical, syntactical, and semantic analysers), but no code is to be generated.
   557  * lexical, syntactical, and semantic analysers), but no code is to be generated.
   519 disable_code_generation_pragma	"{disable code generation}"
   570 disable_code_generation_pragma	"{disable code generation}"
   520 enable_code_generation_pragma	"{enable code generation}"
   571 enable_code_generation_pragma	"{enable code generation}"
   521 
   572 
   522 
   573 
   523 /* Any other pragma... */
   574 /* Any other pragma... */
   524 
   575 pragma ("{"[^}]*"}")|("{{"([^}]|"}"[^}])*"}}")
   525 pragma "{"[^}]*"}"|"{{"([^}]|"}"[^}])*"}}"
   576 
   526 
   577 
       
   578 
       
   579 /* COMMENTS */
       
   580 /* ======== */
       
   581 
       
   582 /* In order to allow nested comments, comments are handled by a specific comment_state state */
       
   583 /* Whenever a "(*" is found, we push the current state onto the stack, and enter a new instance of the comment_state state.
       
   584  * Whenever a "*)" is found, we pop a state off the stack
       
   585  */
       
   586 
       
   587 /* comments... */
       
   588 comment_beg  "(*"
       
   589 comment_end  "*)"
       
   590 
       
   591 /* However, bison has a shift/reduce conflict in bison, when parsing formal function/FB
       
   592  * invocations with the 'NOT <variable_name> =>' syntax (which needs two look ahead 
       
   593  * tokens to be parsed correctly - and bison being LALR(1) only supports one).
       
   594  * The current work around requires flex to completely parse the '<variable_name> =>'
       
   595  * sequence. This sequence includes whitespace and/or comments between the 
       
   596  * <variable_name> and the "=>" token.
       
   597  * 
       
   598  * This flex rule (sendto_identifier_token) uses the whitespace/comment as trailing context,
       
   599  * which means we can not use the comment_state method of specifying/finding and ignoring 
       
   600  * comments.
       
   601  * 
       
   602  * For this reason only, we must also define what a complete comment looks like, so
       
   603  * it may be used in this rule. Since the rule uses the whitespace_or_comment
       
   604  * construct as trailing context, this definition of comment must not use any
       
   605  * trailing context either.
       
   606  * 
       
   607  * Aditionally, it is not possible to define nested comments in flex without the use of
       
   608  * states, so for this particular location, we do NOT support nested comments.
       
   609  */
   527 /* NOTE: this seemingly unnecessary complex definition is required
   610 /* NOTE: this seemingly unnecessary complex definition is required
   528  *       to be able to eat up comments such as:
   611  *       to be able to eat up comments such as:
   529  *          '(* Testing... ! ***** ******)'
   612  *          '(* Testing... ! ***** ******)'
   530  *       without using the trailing context command in flex (/{context})
   613  *       without using the trailing context command in flex (/{context})
   531  *       since {comment} itself will later be used with
   614  *       since {comment} itself will later be used with
   532  *       trailing context ({comment}/{context})
   615  *       trailing context ({comment}/{context})
   533  */
   616  */
   534 not_asterisk				[^*]
   617 not_asterisk				[^*]
   535 not_close_parenthesis_nor_asterisk	[^*)]
   618 not_close_parenthesis_nor_asterisk	[^*)]
   536 asterisk				"*"
   619 asterisk				"*"
   537 comment_text		{not_asterisk}|(({asterisk}+){not_close_parenthesis_nor_asterisk})
   620 comment_text	({not_asterisk})|(({asterisk}+){not_close_parenthesis_nor_asterisk})
   538 
       
   539 comment		"(*"({comment_text}*)({asterisk}+)")"
   621 comment		"(*"({comment_text}*)({asterisk}+)")"
   540 
   622 
   541 
   623 
       
   624 
       
   625 /* 3.1 Whitespace */
       
   626 /* ============== */
   542 /*
   627 /*
   543 3.1 Whitespace
   628  * Whitespace is clearly defined (see IEC 61131-3 v2, section 2.1.4)
   544  (NOTE: Whitespace IS clearly defined, to include newline!!! See section 2.1.4!!!)
   629  * 
   545  No definition of whitespace is given, in other words, the characters that may be used to seperate language tokens are not pecisely defined. One may nevertheless make an inteligent guess of using the space (' '), and other characters also commonly considered whitespace in other programming languages (horizontal tab, vertical tab, form feed, etc.).
   630  * Whitespace definition includes the newline character.
   546  The main question is whether the newline character should be considered whitespace. IL language statements use an EOL token (End Of Line) to distinguish between some language constructs. The EOL token itself is openly defined as "normally consist[ing] of the 'paragraph separator' ", leaving the final choice open to each implemention. If we choose the newline character to represent the EOL token, it may then not be considered whitespace.
   631  * 
   547  On the other hand, some examples that come in a non-normative annex of the specification allow function declarations to span multiple3.1 Whitespace
   632  * However, the standard is inconsistent in that in IL the newline character 
   548  (NOTE: Whitespace IS clearly defined, to include newline!!! See section 2.1.4!!!)
   633  * is considered a token (EOL - end of line). 
   549  No definition of whitespace is given, in other words, the characters that may be used to seperate language tokens are not pecisely defined. One may nevertheless make an inteligent guess of using the space (' '), and other characters also commonly considered whitespace in other programming languages (horizontal tab, vertical tab, form feed, etc.).
   634  * In our implementation we therefore have two definitions of whitespace
   550  The main question is whether the newline character should be considered whitespace. IL language statements use an EOL token (End Of Line) to distinguish between some language constructs. The EOL token itself is openly defined as "normally consist[ing] of the 'paragraph separator' ", leaving the final choice open to each implemention. If we choose the newline character to represent the EOL token, it may then not be considered whitespace.
   635  *   - one for ST, that includes the newline character
   551  On the other hand, some examples that come in a non-normative annex of the specification allow function declarations to span multiple lines, which means that the newline character is being considered as whitespace.
   636  *   - one for IL without the newline character.
   552  Our implementation works around this issue by including the new line character in the whitespace while parsing function declarations and the ST language, and parsing it as the EOL token only while parsing IL language statements. This requires the use of a state machine in the lexical parser that needs at least some knowledge of the syntax itself.
   637  * Additionally, when parsing IL, the newline character is treated as the EOL token.
   553 */
   638  * This requires the use of a state machine in the lexical parser that needs at least 
   554 /* NOTE: Our definition of whitespace will only work in ASCII!
   639  * some knowledge of the syntax itself.
   555  *
   640  *
   556  *       Since the IL language needs to know the location of newline
   641  * NOTE: Our definition of whitespace will only work in ASCII!
   557  *       (token EOL -> '\n' ), we need one definition of whitespace
   642  *
   558  *       for each language...
       
   559  */
       
   560 /*
       
   561  * NOTE: we cannot use
   643  * NOTE: we cannot use
   562  *         st_whitespace	[:space:]*
   644  *         st_whitespace	[:space:]*
   563  *       since we use {st_whitespace} as trailing context. In our case
   645  *       since we use {st_whitespace} as trailing context. In our case
   564  *       this would not constitute "dangerous trailing context", but the
   646  *       this would not constitute "dangerous trailing context", but the
   565  *       lexical generator (i.e. flex) does not know this (since it does
   647  *       lexical generator (i.e. flex) does not know this (since it does
   567  *       generate a "dangerous trailing context" warning!
   649  *       generate a "dangerous trailing context" warning!
   568  *       We use this alternative just to stop the flex utility from
   650  *       We use this alternative just to stop the flex utility from
   569  *       generating the invalid (in this case) warning...
   651  *       generating the invalid (in this case) warning...
   570  */
   652  */
   571 
   653 
   572 st_whitespace_only	[ \f\n\r\t\v]*
   654 st_whitespace			[ \f\n\r\t\v]*
   573 il_whitespace_only	[ \f\r\t\v]*
   655 il_whitespace			[ \f\r\t\v]*
   574 
   656 
   575 st_whitespace_text	{st_whitespace_only}|{comment}|{pragma}
   657 st_whitespace_or_pragma_or_commentX	({st_whitespace})|({pragma})|({comment})
   576 il_whitespace_text	{il_whitespace_only}|{comment}|{pragma}
   658 il_whitespace_or_pragma_or_commentX	({il_whitespace})|({pragma})|({comment})
   577 
   659 
   578 st_whitespace	{st_whitespace_text}*
   660 st_whitespace_or_pragma_or_comment	{st_whitespace_or_pragma_or_commentX}*
   579 il_whitespace	{il_whitespace_text}*
   661 il_whitespace_or_pragma_or_comment	{il_whitespace_or_pragma_or_commentX}*
   580 
   662 
   581 st_whitespace_text_no_pragma	{st_whitespace_only}|{comment}
   663 
   582 il_whitespace_text_no_pragma	{il_whitespace_only}|{comment}
   664 
   583 
   665 qualified_identifier	{identifier}(\.{identifier})+
   584 st_whitespace_no_pragma	{st_whitespace_text_no_pragma}*
       
   585 il_whitespace_no_pragma	{il_whitespace_text_no_pragma}*
       
   586 
       
   587 qualified_identifier	{identifier}(\.{identifier})*
       
   588 
   666 
   589 
   667 
   590 
   668 
   591 /*****************************************/
   669 /*****************************************/
   592 /* B.1.1 Letters, digits and identifiers */
   670 /* B.1.1 Letters, digits and identifiers */
   731  *       days         ::= fixed_point 'd' | integer 'd' ['_'] hours
   809  *       days         ::= fixed_point 'd' | integer 'd' ['_'] hours
   732  *       hours        ::= fixed_point 'h' | integer 'h' ['_'] minutes
   810  *       hours        ::= fixed_point 'h' | integer 'h' ['_'] minutes
   733  *       minutes      ::= fixed_point 'm' | integer 'm' ['_'] seconds
   811  *       minutes      ::= fixed_point 'm' | integer 'm' ['_'] seconds
   734  *       seconds      ::= fixed_point 's' | integer 's' ['_'] milliseconds
   812  *       seconds      ::= fixed_point 's' | integer 's' ['_'] milliseconds
   735  *       milliseconds ::= fixed_point 'ms'
   813  *       milliseconds ::= fixed_point 'ms'
   736 
       
   737  */
   814  */
   738 
   815 
   739 interval_ms_X		({integer_0_999}(\.{integer})?)ms
   816 interval_ms_X		({integer_0_999}(\.{integer})?)ms
   740 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)
   741 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)
   851 <INITIAL>{file_include_pragma}	unput_text(0); yy_push_state(include_beg);
   928 <INITIAL>{file_include_pragma}	unput_text(0); yy_push_state(include_beg);
   852 
   929 
   853 	/* Pragmas sent to syntax analyser (bison) */
   930 	/* Pragmas sent to syntax analyser (bison) */
   854 {disable_code_generation_pragma}               return disable_code_generation_pragma_token;
   931 {disable_code_generation_pragma}               return disable_code_generation_pragma_token;
   855 {enable_code_generation_pragma}                return enable_code_generation_pragma_token;
   932 {enable_code_generation_pragma}                return enable_code_generation_pragma_token;
   856 <body_state>{disable_code_generation_pragma}   return disable_code_generation_pragma_token;
   933 <body_state,vardecl_list_state>{disable_code_generation_pragma}   return disable_code_generation_pragma_token;
   857 <body_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;
   858 
   935 
   859 	/* 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...   */
   860 	/* 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. */
   861 {pragma}	{/* return the pragmma without the enclosing '{' and '}' */
   938 {pragma}	{/* return the pragmma without the enclosing '{' and '}' */
   862          int cut = yytext[1]=='{'?2:1;
   939 		 int cut = yytext[1]=='{'?2:1;
   863 		 yytext[strlen(yytext)-cut] = '\0';
   940 		 yytext[strlen(yytext)-cut] = '\0';
   864 		 yylval.ID=strdup(yytext+cut);
   941 		 yylval.ID=strdup(yytext+cut);
   865 		 return pragma_token;
   942 		 return pragma_token;
   866 		}
   943 		}
   867 <body_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */
   944 <body_state,vardecl_list_state>{pragma} {/* return the pragmma without the enclosing '{' and '}' */
   868 		 int cut = yytext[1]=='{'?2:1;
   945 		 int cut = yytext[1]=='{'?2:1;
   869          yytext[strlen(yytext)-cut] = '\0';
   946 		 yytext[strlen(yytext)-cut] = '\0';
   870 		 yylval.ID=strdup(yytext+cut);
   947 		 yylval.ID=strdup(yytext+cut);
   871 		 return pragma_token;
   948 		 return pragma_token;
   872 		}
   949 		}
   873 
   950 
   874 
   951 
   948 
  1025 
   949 	/*********************************/
  1026 	/*********************************/
   950 	/* Handle all the state changes! */
  1027 	/* Handle all the state changes! */
   951 	/*********************************/
  1028 	/*********************************/
   952 
  1029 
   953 	/* INITIAL -> decl_state */
  1030 	/* INITIAL -> header_state */
   954 <INITIAL>{
  1031 <INITIAL>{
   955 	/* NOTE: how about functions that do not declare variables, and go directly to the body_state???
  1032 	/* NOTE: how about functions that do not declare variables, and go directly to the body_state???
   956 	 *      - According to Section 2.5.1.3 (Function Declaration), item 2 in the list, a FUNCTION
  1033 	 *      - According to Section 2.5.1.3 (Function Declaration), item 2 in the list, a FUNCTION
   957 	 *        must have at least one input argument, so a correct declaration will have at least
  1034 	 *        must have at least one input argument, so a correct declaration will have at least
   958 	 *        one VAR_INPUT ... VAR_END construct!
  1035 	 *        one VAR_INPUT ... VAR_END construct!
   964 	 *        construct!
  1041 	 *        construct!
   965 	 *
  1042 	 *
   966 	 *       All the above means that we needn't worry about PROGRAMs, FUNCTIONs or
  1043 	 *       All the above means that we needn't worry about PROGRAMs, FUNCTIONs or
   967 	 *       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.
   968 	 *       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
   969 	 *       continue in the <decl_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
   970 	 *       or PROGAM.
  1047 	 *       or PROGAM.
   971 	 */
  1048 	 */
   972 FUNCTION				BEGIN(decl_state); return FUNCTION;
  1049 FUNCTION				yy_push_state(header_state); return FUNCTION;
   973 FUNCTION_BLOCK				BEGIN(decl_state); return FUNCTION_BLOCK;
  1050 FUNCTION_BLOCK				yy_push_state(header_state); return FUNCTION_BLOCK;
   974 PROGRAM					BEGIN(decl_state); return PROGRAM;
  1051 PROGRAM					yy_push_state(header_state); return PROGRAM;
   975 CONFIGURATION				BEGIN(config_state); return CONFIGURATION;
  1052 CONFIGURATION				BEGIN(config_state); return CONFIGURATION;
   976 }
  1053 }
   977 
  1054 
   978 	/* INITIAL -> body_state */
  1055 	/* INITIAL -> body_state */
   979 	/* required if the function, program, etc.. has no VAR block! */
  1056 	/* required if the function, program, etc.. has no VAR block! */
   987 FUNCTION_BLOCK	BEGIN(body_state); return FUNCTION_BLOCK;
  1064 FUNCTION_BLOCK	BEGIN(body_state); return FUNCTION_BLOCK;
   988 PROGRAM		BEGIN(body_state); return PROGRAM;
  1065 PROGRAM		BEGIN(body_state); return PROGRAM;
   989 }
  1066 }
   990 	*/
  1067 	*/
   991 
  1068 
   992 	/* decl_state -> (body_state | sfc_state) */
  1069 	/* header_state -> (vardecl_list_state) */
   993 <decl_state>{
  1070 <header_state>{
   994 END_VAR{st_whitespace}VAR		{unput_text(strlen("END_VAR")); 
  1071 VAR				| /* execute the next rule's action, i.e. fall-through! */
   995 					 return END_VAR;
  1072 VAR_INPUT			|
   996 					}
  1073 VAR_OUTPUT			|
   997 END_VAR{st_whitespace}INITIAL_STEP	{unput_text(strlen("END_VAR")); 
  1074 VAR_IN_OUT			|
   998 					 yy_push_state(sfc_state); 
  1075 VAR_EXTERNAL			|
   999 					 return END_VAR;
  1076 VAR_GLOBAL			|
  1000 					}
  1077 VAR_TEMP			|
  1001 END_VAR{st_whitespace}			{unput_text(strlen("END_VAR")); 
  1078 VAR_CONFIG			|
  1002 					 cmd_goto_body_state(); 
  1079 VAR_ACCESS			unput_text(0); BEGIN(vardecl_list_state);
  1003 					 return END_VAR;
  1080 }
  1004 					}
  1081 
  1005 }
  1082 
  1006 
  1083 	/* vardecl_list_state -> (vardecl_state | body_state | INITIAL) */
  1007 	/* body_state -> (il_state | st_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			|
       
  1093 VAR				unput_text(0); yy_push_state(vardecl_state);
       
  1094 
       
  1095 END_FUNCTION			unput_text(0); BEGIN(INITIAL); 
       
  1096 END_FUNCTION_BLOCK		unput_text(0); BEGIN(INITIAL); 
       
  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) */
       
  1104 <vardecl_state>{
       
  1105 END_VAR				yy_pop_state(); return END_VAR; /* pop back to header_state */
       
  1106 }
       
  1107 
       
  1108 
       
  1109 	/* body_state -> (il_state | st_state | sfc_state) */
  1008 <body_state>{
  1110 <body_state>{
  1009 {st_whitespace_no_pragma}			/* Eat any whitespace */
  1111 INITIAL_STEP			unput_text(0); BEGIN(sfc_state); 
  1010 {qualified_identifier}{st_whitespace}":="	unput_text(0); BEGIN(st_state);
  1112 
  1011 {direct_variable_standard}{st_whitespace}":="	unput_text(0); BEGIN(st_state);
  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 */
  1012 {qualified_identifier}"["			unput_text(0); BEGIN(st_state);
  1114 {direct_variable_standard}	unput_text(0); BEGIN(st_state); /* will always be followed by ':=' as the left hand of an assignment statement */
  1013 
  1115 
  1014 RETURN						unput_text(0); BEGIN(st_state);
  1116 RETURN				unput_text(0); BEGIN(st_state);
  1015 IF						unput_text(0); BEGIN(st_state);
  1117 IF				unput_text(0); BEGIN(st_state);
  1016 CASE						unput_text(0); BEGIN(st_state);
  1118 CASE				unput_text(0); BEGIN(st_state);
  1017 FOR						unput_text(0); BEGIN(st_state);
  1119 FOR				unput_text(0); BEGIN(st_state);
  1018 WHILE						unput_text(0); BEGIN(st_state);
  1120 WHILE				unput_text(0); BEGIN(st_state);
  1019 REPEAT						unput_text(0); BEGIN(st_state);
  1121 EXIT				unput_text(0); BEGIN(st_state);
  1020 EXIT						unput_text(0); BEGIN(st_state);
  1122 REPEAT				unput_text(0); BEGIN(st_state);
  1021 
  1123 
  1022 	/* ':=' occurs only in transitions, and not Function or FB bodies! */
  1124 	/* ':=' occurs only in transitions, and not Function or FB bodies! */
  1023 :=						unput_text(0); BEGIN(st_state);
  1125 :=				unput_text(0); BEGIN(st_state);
  1024 
       
  1025 	/* Hopefully, the above rules (along with the last one),
       
  1026          * used to distinguish ST from IL, are 
       
  1027 	 * enough to handle all ocurrences. However, if
       
  1028 	 * there is some situation where the compiler is getting confused,
       
  1029 	 * we add the following rule to detect 'label:' in IL code. This will
       
  1030 	 * allow the user to insert a label right at the beginning (which
       
  1031 	 * will probably not be used further by his code) simply as a way
       
  1032 	 * to force the compiler to interpret his code as IL code.
       
  1033 	 */
       
  1034 {identifier}{st_whitespace}":"{st_whitespace}	unput_text(0); BEGIN(il_state);
       
  1035 
  1126 
  1036 {identifier}	{int token = get_identifier_token(yytext);
  1127 {identifier}	{int token = get_identifier_token(yytext);
  1037 		 if (token == prev_declared_fb_name_token) {
  1128 		 if ((token == prev_declared_fb_name_token) || (token == prev_declared_variable_name_token)) {
  1038 		   /* the code has a call to a function block */
  1129 		   /* the code has a call to a function block OR has an assingment with a variable as the lvalue */
  1039 		   /* NOTE: if we ever decide to allow the user to use IL operator tokens
  1130 		   unput_text(0); BEGIN(st_state);
  1040 		    * (LD, ST, ...) as identifiers for variable names (including
  1131 		 } else
  1041 		    * function block instances), then the above inference/conclusion 
  1132  		 if (token == prev_declared_derived_function_name_token) {
  1042 		    * may be incorrect, and this condition may have to be changed!
  1133 		   /* the code has a call to a function - must be IL */
  1043 		    */	
  1134 		   unput_text(0); BEGIN(il_state);
  1044 		   BEGIN(st_state);
       
  1045 		 } else {
  1135 		 } else {
  1046 		   BEGIN(il_state);
  1136 		   /* Might be a lable in IL, or a bug in ST/IL code. We jump to IL */
       
  1137 		   unput_text(0); BEGIN(il_state);
  1047 		 }
  1138 		 }
  1048 		 unput_text(0);
       
  1049 		}
  1139 		}
  1050 
  1140 
  1051 .		unput_text(0); BEGIN(il_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... */
  1052 }	/* end of body_state lexical parser */
  1142 }	/* end of body_state lexical parser */
  1053 
  1143 
  1054 	/* (il_state | st_state) -> $previous_state (decl_state or sfc_state) */
  1144 
       
  1145 
       
  1146 	/* (il_state | st_state) -> pop to $previous_state (vardecl_list_state or sfc_state) */
  1055 <il_state,st_state>{
  1147 <il_state,st_state>{
  1056 END_FUNCTION		yy_pop_state(); unput_text(0);
  1148 END_FUNCTION		yy_pop_state(); unput_text(0);
  1057 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1149 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1058 END_PROGRAM		yy_pop_state(); unput_text(0);
  1150 END_PROGRAM		yy_pop_state(); unput_text(0);
  1059 END_TRANSITION		yy_pop_state(); unput_text(0);
  1151 END_TRANSITION		yy_pop_state(); unput_text(0);
  1060 END_ACTION		yy_pop_state(); unput_text(0);
  1152 END_ACTION		yy_pop_state(); unput_text(0);
  1061 }
  1153 }
  1062 
  1154 
  1063 	/* sfc_state -> INITIAL */
  1155 	/* sfc_state -> pop to $previous_state (vardecl_list_state or sfc_state) */
  1064 <sfc_state>{
  1156 <sfc_state>{
  1065 END_FUNCTION		yy_pop_state(); unput_text(0);
  1157 END_FUNCTION		yy_pop_state(); unput_text(0);
  1066 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1158 END_FUNCTION_BLOCK	yy_pop_state(); unput_text(0);
  1067 END_PROGRAM		yy_pop_state(); unput_text(0);
  1159 END_PROGRAM		yy_pop_state(); unput_text(0);
  1068 }
  1160 }
  1069 
  1161 
  1070 	/* decl_state -> INITIAL */
       
  1071 <decl_state>{
       
  1072 END_FUNCTION		BEGIN(INITIAL); return END_FUNCTION;
       
  1073 END_FUNCTION_BLOCK	BEGIN(INITIAL); return END_FUNCTION_BLOCK;
       
  1074 END_PROGRAM		BEGIN(INITIAL); return END_PROGRAM;
       
  1075 }
       
  1076 	/* config -> INITIAL */
  1162 	/* config -> INITIAL */
  1077 END_CONFIGURATION	BEGIN(INITIAL); return END_CONFIGURATION;
  1163 END_CONFIGURATION	BEGIN(INITIAL); return END_CONFIGURATION;
  1078 
  1164 
  1079 
  1165 
  1080 
  1166 
  1081 	/***************************************/
  1167 	/***************************************/
  1082 	/* Next is to to remove all whitespace */
  1168 	/* Next is to to remove all whitespace */
  1083 	/***************************************/
  1169 	/***************************************/
  1084 	/* NOTE: pragmas are handled right at the beginning... */
  1170 	/* NOTE: pragmas are handled right at the beginning... */
  1085 
  1171 
  1086 <INITIAL,config_state,decl_state,st_state,sfc_state,task_init_state,sfc_qualifier_state>{st_whitespace_no_pragma}	/* Eat any whitespace */
  1172 	/* The whitespace */
  1087 <il_state>{il_whitespace_no_pragma}		/* Eat any whitespace */
  1173 <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 */
  1088 
  1174 <il_state>{il_whitespace}		/* Eat any whitespace */
  1089 
  1175 
       
  1176 	/* The comments */
       
  1177 <body_state,vardecl_list_state>{comment_beg}		yy_push_state(comment_state);
       
  1178 {comment_beg}						yy_push_state(comment_state);
       
  1179 <comment_state>{
       
  1180 {comment_beg}						{if (get_opt_nested_comments()) yy_push_state(comment_state);}
       
  1181 {comment_end}						yy_pop_state();
       
  1182 .							/* Ignore text inside comment! */
       
  1183 \n							/* Ignore text inside comment! */
       
  1184 }
  1090 
  1185 
  1091 	/*****************************************/
  1186 	/*****************************************/
  1092 	/* B.1.1 Letters, digits and identifiers */
  1187 	/* B.1.1 Letters, digits and identifiers */
  1093 	/*****************************************/
  1188 	/*****************************************/
  1094 	/* NOTE: 'R1', 'IN', etc... are IL operators, and therefore tokens
  1189 	/* NOTE: 'R1', 'IN', etc... are IL operators, and therefore tokens
  1637 
  1732 
  1638 
  1733 
  1639 	/*****************************************/
  1734 	/*****************************************/
  1640 	/* B.1.1 Letters, digits and identifiers */
  1735 	/* B.1.1 Letters, digits and identifiers */
  1641 	/*****************************************/
  1736 	/*****************************************/
  1642 <st_state>{identifier}/({st_whitespace})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
  1737 <st_state>{identifier}/({st_whitespace_or_pragma_or_comment})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
  1643 <il_state>{identifier}/({il_whitespace})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
  1738 <il_state>{identifier}/({il_whitespace_or_pragma_or_comment})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
  1644 {identifier} 				{yylval.ID=strdup(yytext);
  1739 {identifier} 				{yylval.ID=strdup(yytext);
  1645 					 // printf("returning identifier...: %s, %d\n", yytext, get_identifier_token(yytext));
  1740 					 // printf("returning identifier...: %s, %d\n", yytext, get_identifier_token(yytext));
  1646 					 return get_identifier_token(yytext);}
  1741 					 return get_identifier_token(yytext);}
  1647 
  1742 
  1648 
  1743