stage1_2/iec_flex.ll
changeset 547 dab341e80664
parent 415 5c115720149c
child 616 0c7663fdc8d3
equal deleted inserted replaced
546:8cc4c51c4bfc 547:dab341e80664
    89  * function from the resulting c code, so the compiler 
    89  * function from the resulting c code, so the compiler 
    90  * no longer complains.
    90  * no longer complains.
    91  */
    91  */
    92 %option noyy_top_state
    92 %option noyy_top_state
    93 
    93 
    94 /* We will not be using unput() in our flex code... */
    94 /* We will be using unput() in our flex code, so we cannot set the following option!... */
       
    95 /*
    95 %option nounput
    96 %option nounput
       
    97 */
    96 
    98 
    97 /**************************************************/
    99 /**************************************************/
    98 /* External Variable and Function declarations... */
   100 /* External Variable and Function declarations... */
    99 /**************************************************/
   101 /**************************************************/
   100 
   102 
   239 /***************************************************/
   241 /***************************************************/
   240 
   242 
   241 %{
   243 %{
   242 /* return all the text in the current token back to the input stream. */
   244 /* return all the text in the current token back to the input stream. */
   243 void unput_text(unsigned int n);
   245 void unput_text(unsigned int n);
       
   246 /* return all the text in the current token back to the input stream, 
       
   247  * but first return to the stream an additional character to mark the end of the token. 
       
   248  */
       
   249 void unput_and_mark(const char c);
   244 %}
   250 %}
   245 
   251 
   246 
   252 
   247 
   253 
   248 /****************************/
   254 /****************************/
   337  * these tokens are not reserved keywords, which means it should be possible to
   343  * these tokens are not reserved keywords, which means it should be possible to
   338  * define variables/functions/FBs with any of these names (including 
   344  * define variables/functions/FBs with any of these names (including 
   339  * S and R which are special because they are also IL operators). So, when we are not
   345  * S and R which are special because they are also IL operators). So, when we are not
   340  * expecting any action qualifiers, flex does not return these tokens, and is free
   346  * expecting any action qualifiers, flex does not return these tokens, and is free
   341  * to interpret them as previously defined variables/functions/... as the case may be.
   347  * to interpret them as previously defined variables/functions/... as the case may be.
       
   348  *
       
   349  * The time_literal_state is required because TIME# literals are decomposed into 
       
   350  * portions, and wewant to send these portions one by one to bison. Each poertion will 
       
   351  * represent the value in days/hours/minutes/seconds/ms.
       
   352  * Unfortunately, some of these portions may also be lexically analysed as an identifier. So,
       
   353  * we need to disable lexical identification of identifiers while parsing TIME# literals!
       
   354  * e.g.:  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',
       
   357  *       and return that identifier instead! So, we added this state!
   342  *
   358  *
   343  * The state machine has 7 possible states (INITIAL, config, decl, body, st, il, sfc)
   359  * The state machine has 7 possible states (INITIAL, config, decl, body, st, il, sfc)
   344  * Possible state changes are:
   360  * Possible state changes are:
   345  *   INITIAL -> goto(decl_state)
   361  *   INITIAL -> goto(decl_state)
   346  *               (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found,
   362  *               (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found,
   416 %s sfc_qualifier_state
   432 %s sfc_qualifier_state
   417 
   433 
   418 /* we are parsing sfc code, and expecting the priority token.       */
   434 /* we are parsing sfc code, and expecting the priority token.       */
   419 %s sfc_priority_state
   435 %s sfc_priority_state
   420 
   436 
   421 
   437 /* we are parsing a TIME# literal. We must not return any {identifier} tokens. */
       
   438 %x time_literal_state
   422 
   439 
   423 
   440 
   424 /*******************/
   441 /*******************/
   425 /* File #include's */
   442 /* File #include's */
   426 /*******************/
   443 /*******************/
   596 
   613 
   597 /******************************/
   614 /******************************/
   598 /* B.1.2.1   Numeric literals */
   615 /* B.1.2.1   Numeric literals */
   599 /******************************/
   616 /******************************/
   600 integer         {digit}((_?{digit})*)
   617 integer         {digit}((_?{digit})*)
       
   618 
       
   619 /* Some helper symbols for parsing TIME literals... */
       
   620 integer_0_59    (0(_?))*([0-5](_?))?{digit}
       
   621 integer_0_19    (0(_?))*([0-1](_?))?{digit}
       
   622 integer_20_23   (0(_?))*2(_?)[0-3]
       
   623 integer_0_23    {integer_0_19}|{integer_20_23}
       
   624 integer_0_999   {digit}((_?{digit})?)((_?{digit})?)
       
   625 
       
   626 
   601 binary_integer  2#{bit}((_?{bit})*)
   627 binary_integer  2#{bit}((_?{bit})*)
   602 bit		[0-1]
   628 bit		[0-1]
   603 octal_integer   8#{octal_digit}((_?{octal_digit})*)
   629 octal_integer   8#{octal_digit}((_?{octal_digit})*)
   604 hex_integer     16#{hex_digit}((_?{hex_digit})*)
   630 hex_integer     16#{hex_digit}((_?{hex_digit})*)
   605 exponent        [Ee]([+-]?){integer}
   631 exponent        [Ee]([+-]?){integer}
   671 /************************/
   697 /************************/
   672 /* B 1.2.3.1 - Duration */
   698 /* B 1.2.3.1 - Duration */
   673 /************************/
   699 /************************/
   674 fixed_point		{integer}\.{integer}
   700 fixed_point		{integer}\.{integer}
   675 
   701 
   676 fixed_point_d		{fixed_point}d
   702 
   677 integer_d		{integer}d
   703 /* NOTE: The IEC 61131-3 v2 standard has an incorrect formal syntax definition of duration,
   678 
   704  *       as its definition does not match the standard's text.
   679 fixed_point_h		{fixed_point}h
   705  *       IEC 61131-3 v3 (committee draft) seems to have this fixed, so we use that
   680 integer_h		{integer}h
   706  *       definition instead!
   681 
   707  *
   682 fixed_point_m		{fixed_point}m
   708  *       duration::= ('T' | 'TIME') '#' ['+'|'-'] interval
   683 integer_m		{integer}m
   709  *       interval::= days | hours | minutes | seconds | milliseconds
   684 
   710  *       fixed_point  ::= integer [ '.' integer]
   685 fixed_point_s		{fixed_point}s
   711  *       days         ::= fixed_point 'd' | integer 'd' ['_'] [ hours ]
   686 integer_s		{integer}s
   712  *       hours        ::= fixed_point 'h' | integer 'h' ['_'] [ minutes ]
   687 
   713  *       minutes      ::= fixed_point 'm' | integer 'm' ['_'] [ seconds ]
   688 fixed_point_ms		{fixed_point}ms
   714  *       seconds      ::= fixed_point 's' | integer 's' ['_'] [ milliseconds ]
   689 integer_ms		{integer}ms
   715  *       milliseconds ::= fixed_point 'ms'
   690 
   716  * 
       
   717  * 
       
   718  *  The original IEC 61131-3 v2 definition is:
       
   719  *       duration ::= ('T' | 'TIME') '#' ['-'] interval
       
   720  *       interval ::= days | hours | minutes | seconds | milliseconds
       
   721  *       fixed_point  ::= integer [ '.' integer]
       
   722  *       days         ::= fixed_point 'd' | integer 'd' ['_'] hours
       
   723  *       hours        ::= fixed_point 'h' | integer 'h' ['_'] minutes
       
   724  *       minutes      ::= fixed_point 'm' | integer 'm' ['_'] seconds
       
   725  *       seconds      ::= fixed_point 's' | integer 's' ['_'] milliseconds
       
   726  *       milliseconds ::= fixed_point 'ms'
       
   727 
       
   728  */
       
   729 
       
   730 interval_ms_X		({integer_0_999}(\.{integer})?)ms
       
   731 interval_s_X		{integer_0_59}s(_?{interval_ms_X})?
       
   732 interval_m_X		{integer_0_59}m(_?{interval_s_X})?
       
   733 interval_h_X		{integer_0_23}h(_?{interval_m_X})?
       
   734 
       
   735 interval_ms		{integer}ms|({fixed_point}ms)
       
   736 interval_s		{integer}s(_?{interval_ms_X})?|({fixed_point}s)
       
   737 interval_m		{integer}m(_?{interval_s_X})?|({fixed_point}m)
       
   738 interval_h		{integer}h(_?{interval_m_X})?|({fixed_point}h)
       
   739 interval_d		{integer}d(_?{interval_h_X})?|({fixed_point}d)
       
   740 
       
   741 interval		{interval_ms}|{interval_s}|{interval_m}|{interval_h}|{interval_d}
       
   742 
       
   743 /* to help provide nice error messages, we also parse an incorrect but plausible interval... */
       
   744 /* NOTE that this erroneous interval will be parsed outside the time_literal_state, so must not 
       
   745  *      be able to parse any other legal lexcial construct (besides a legal interval, but that
       
   746  *      is OK as this rule will appear _after_ the rule to parse legal intervals!).
       
   747  */
       
   748 fixed_point_or_integer  {fixed_point}|{integer}
       
   749 erroneous_interval	({fixed_point_or_integer}d_?)?({fixed_point_or_integer}h_?)?({fixed_point_or_integer}m_?)?({fixed_point_or_integer}s_?)?({fixed_point_or_integer}ms)?
   691 
   750 
   692 /********************************************/
   751 /********************************************/
   693 /* B.1.4.1   Directly Represented Variables */
   752 /* B.1.4.1   Directly Represented Variables */
   694 /********************************************/
   753 /********************************************/
   695 /* The correct definition, if the standard were to be followed... */
   754 /* The correct definition, if the standard were to be followed... */
   717  *       AT %I3 : BYTE := 255;
   776  *       AT %I3 : BYTE := 255;
   718  *    END_VAR
   777  *    END_VAR
   719  *    in which case we are currently using "%I3" as the variable
   778  *    in which case we are currently using "%I3" as the variable
   720  *    name.
   779  *    name.
   721  */
   780  */
   722 direct_variable_matplc		%{identifier}
   781 /* direct_variable_matplc		%{identifier} */
   723 
   782 /* direct_variable			{direct_variable_standard}|{direct_variable_matplc} */
   724 direct_variable			{direct_variable_standard}|{direct_variable_matplc}
   783 direct_variable			{direct_variable_standard}
   725 
   784 
   726 /******************************************/
   785 /******************************************/
   727 /* B 1.4.3 - Declaration & Initialisation */
   786 /* B 1.4.3 - Declaration & Initialisation */
   728 /******************************************/
   787 /******************************************/
   729 incompl_location	%[IQM]\*
   788 incompl_location	%[IQM]\*
  1539 
  1598 
  1540 	/************************/
  1599 	/************************/
  1541 	/* B 1.2.3.1 - Duration */
  1600 	/* B 1.2.3.1 - Duration */
  1542 	/************************/
  1601 	/************************/
  1543 {fixed_point}		{yylval.ID=strdup(yytext); return fixed_point_token;}
  1602 {fixed_point}		{yylval.ID=strdup(yytext); return fixed_point_token;}
  1544 
  1603 {interval}		{/*fprintf(stderr, "entering time_literal_state ##%s##\n", yytext);*/ unput_and_mark('#'); yy_push_state(time_literal_state);}
  1545 {fixed_point_d}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_d_token;}
  1604 {erroneous_interval}	{return erroneous_interval_token;}
  1546 {integer_d}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_d_token;}
  1605 
  1547 
  1606 <time_literal_state>{
  1548 {fixed_point_h}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_h_token;}
  1607 {integer}d		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_d_token;}
  1549 {integer_h}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_h_token;}
  1608 {integer}h		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_h_token;}
  1550 
  1609 {integer}m		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_m_token;}
  1551 {fixed_point_m}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_m_token;}
  1610 {integer}s		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_s_token;}
  1552 {integer_m}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_m_token;}
  1611 {integer}ms		{yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return integer_ms_token;}
  1553 
  1612 {fixed_point}d		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_d_token;}
  1554 {fixed_point_s}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_s_token;}
  1613 {fixed_point}h		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_h_token;}
  1555 {integer_s}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_s_token;}
  1614 {fixed_point}m		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_m_token;}
  1556 
  1615 {fixed_point}s		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_s_token;}
  1557 {fixed_point_ms}	{yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return fixed_point_ms_token;}
  1616 {fixed_point}ms		{yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return fixed_point_ms_token;}
  1558 {integer_ms}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return integer_ms_token;}
  1617 
  1559 
  1618 _			/* do nothing - eat it up!*/
  1560 
  1619 \#			{/*fprintf(stderr, "poping from time_literal_state (###)\n");*/ yy_pop_state(); return end_interval_token;}
       
  1620 .			{ERROR;}
       
  1621 \n			{ERROR;}
       
  1622 }
  1561 	/*******************************/
  1623 	/*******************************/
  1562 	/* B.1.2.2   Character Strings */
  1624 	/* B.1.2.2   Character Strings */
  1563 	/*******************************/
  1625 	/*******************************/
  1564 {double_byte_character_string} {yylval.ID=strdup(yytext); return double_byte_character_string_token;}
  1626 {double_byte_character_string} {yylval.ID=strdup(yytext); return double_byte_character_string_token;}
  1565 {single_byte_character_string} {yylval.ID=strdup(yytext); return single_byte_character_string_token;}
  1627 {single_byte_character_string} {yylval.ID=strdup(yytext); return single_byte_character_string_token;}
  1641       current_tracking->lineNumber--;*/
  1703       current_tracking->lineNumber--;*/
  1642 
  1704 
  1643   /* now return all the text back to the input stream... */
  1705   /* now return all the text back to the input stream... */
  1644   yyless(n);
  1706   yyless(n);
  1645 }
  1707 }
       
  1708 
       
  1709 
       
  1710 /* return all the text in the current token back to the input stream, 
       
  1711  * but first return to the stream an additional character to mark the end of the token. 
       
  1712  */
       
  1713 void unput_and_mark(const char c) {
       
  1714   char *yycopy = strdup( yytext ); /* unput() destroys yytext, so we copy it first */
       
  1715   unput(c);
       
  1716   for (int i = yyleng-1; i >= 0; i--)
       
  1717     unput(yycopy[i]);
       
  1718 
       
  1719   free(yycopy);
       
  1720 }
       
  1721 
  1646 
  1722 
  1647 
  1723 
  1648 /* Called by flex when it reaches the end-of-file */
  1724 /* Called by flex when it reaches the end-of-file */
  1649 int yywrap(void)
  1725 int yywrap(void)
  1650 {
  1726 {