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 |
169 * of the token being parsed. |
171 * of the token being parsed. |
170 * This is only needed if we want to keep |
172 * This is only needed if we want to keep |
171 * track of the locations, in order to give |
173 * track of the locations, in order to give |
172 * more meaningful error messages! |
174 * more meaningful error messages! |
173 */ |
175 */ |
174 extern YYLTYPE yylloc; |
176 /* |
175 |
177 *extern YYLTYPE yylloc; |
|
178 b*/ |
176 #define YY_INPUT(buf,result,max_size) {\ |
179 #define YY_INPUT(buf,result,max_size) {\ |
177 result = GetNextChar(buf, max_size);\ |
180 result = GetNextChar(buf, max_size);\ |
178 if ( result <= 0 )\ |
181 if ( result <= 0 )\ |
179 result = YY_NULL;\ |
182 result = YY_NULL;\ |
180 } |
183 } |
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, "popping from time_literal_state (###)\n");*/ yy_pop_state(); return end_interval_token;} |
|
1620 . {/*fprintf(stderr, "time_literal_state: found invalid character '%s'. Aborting!\n", yytext);*/ 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;} |