Fix parsing os TIME literals & rename the extract_integer() function.
--- a/absyntax/absyntax.def Wed May 09 22:59:10 2012 +0100
+++ b/absyntax/absyntax.def Wed May 09 23:00:10 2012 +0100
@@ -210,13 +210,15 @@
/************************/
SYM_REF0(neg_time_c)
SYM_REF3(duration_c, type_name, neg, interval)
+SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds)
SYM_TOKEN(fixed_point_c)
+/*
SYM_REF2(days_c, days, hours)
SYM_REF2(hours_c, hours, minutes)
SYM_REF2(minutes_c, minutes, seconds)
SYM_REF2(seconds_c, seconds, milliseconds)
SYM_REF1(milliseconds_c, milliseconds)
-
+*/
/************************************/
/* B 1.2.3.2 - Time of day and Date */
--- a/absyntax_utils/absyntax_utils.cc Wed May 09 22:59:10 2012 +0100
+++ b/absyntax_utils/absyntax_utils.cc Wed May 09 23:00:10 2012 +0100
@@ -98,20 +98,21 @@
/* extract the value of an integer from an integer_c object !! */
/* NOTE: it must ignore underscores! */
-int extract_integer(symbol_c *sym) {
+long long extract_integer_value(symbol_c *sym) {
std::string str = "";
integer_c *integer;
neg_integer_c * neg_integer;
if ((neg_integer = dynamic_cast<neg_integer_c *>(sym)) != NULL)
- return - extract_integer((integer_c *)neg_integer->exp);
+ return - extract_integer_value(neg_integer->exp);
if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
for(unsigned int i = 0; i < strlen(integer->value); i++)
if (integer->value[i] != '_') str += integer->value[i];
- return atoi(str.c_str());
+ /* return atoi(str.c_str()); */
+ return atoll(str.c_str());
}
--- a/absyntax_utils/absyntax_utils.hh Wed May 09 22:59:10 2012 +0100
+++ b/absyntax_utils/absyntax_utils.hh Wed May 09 23:00:10 2012 +0100
@@ -56,7 +56,7 @@
int compare_identifiers(symbol_c *ident1, symbol_c *ident2);
/* extract the value of an integer from an integer_c object !! */
-int extract_integer(symbol_c *integer);
+long long extract_integer_value(symbol_c *integer);
/* A symbol table with all globally declared functions... */
extern function_declaration_c null_symbol1;
@@ -119,7 +119,6 @@
#include "search_expression_type.hh"
#include "add_en_eno_param_decl.hh"
#include "get_sizeof_datatype.hh"
-#include "get_function_type.h"
#include "search_il_label.hh"
#include "get_var_name.hh"
--- a/absyntax_utils/function_param_iterator.cc Wed May 09 22:59:10 2012 +0100
+++ b/absyntax_utils/function_param_iterator.cc Wed May 09 23:00:10 2012 +0100
@@ -130,7 +130,7 @@
if (extensible_parameter != NULL) {
sym = extensible_parameter->var_name;
current_param_is_extensible = true;
- _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
+ _first_extensible_param_index = extract_integer_value(extensible_parameter->first_index);
}
identifier_c *variable_name = dynamic_cast<identifier_c *>(sym);
if (variable_name == NULL) ERROR;
@@ -167,7 +167,7 @@
if (extensible_parameter != NULL) {
var_name = extensible_parameter->var_name;
current_param_is_extensible = true;
- _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
+ _first_extensible_param_index = extract_integer_value(extensible_parameter->first_index);
}
identifier_c *variable_name = dynamic_cast<identifier_c *>(var_name);
if (variable_name == NULL) ERROR;
@@ -265,7 +265,7 @@
if (extensible_parameter != NULL) {
sym = extensible_parameter->var_name;
current_param_is_extensible = true;
- _first_extensible_param_index = extract_integer(extensible_parameter->first_index);
+ _first_extensible_param_index = extract_integer_value(extensible_parameter->first_index);
current_extensible_param_index = _first_extensible_param_index;
}
identifier = dynamic_cast<identifier_c *>(sym);
--- a/absyntax_utils/search_constant_type.cc Wed May 09 22:59:10 2012 +0100
+++ b/absyntax_utils/search_constant_type.cc Wed May 09 23:00:10 2012 +0100
@@ -105,11 +105,7 @@
void *search_constant_type_c::visit(neg_time_c *symbol) {ERROR; return NULL;} /* this member function should never be called. */
void *search_constant_type_c::visit(duration_c *symbol) {return (void *)(symbol->type_name);}
void *search_constant_type_c::visit(fixed_point_c *symbol) {ERROR; return NULL;} /* this member function should never be called. */
-void *search_constant_type_c::visit(days_c *symbol) {ERROR; return NULL;} /* this member function should never be called. */
-void *search_constant_type_c::visit(hours_c *symbol) {ERROR; return NULL;} /* this member function should never be called. */
-void *search_constant_type_c::visit(minutes_c *symbol) {ERROR; return NULL;} /* this member function should never be called. */
-void *search_constant_type_c::visit(seconds_c *symbol) {ERROR; return NULL;} /* this member function should never be called. */
-void *search_constant_type_c::visit(milliseconds_c *symbol) {ERROR; return NULL;} /* this member function should never be called. */
+void *search_constant_type_c::visit(interval_c *symbol) {ERROR; return NULL;} /* this member function should never be called. */
/************************************/
/* B 1.2.3.2 - Time of day and Date */
--- a/absyntax_utils/search_constant_type.hh Wed May 09 22:59:10 2012 +0100
+++ b/absyntax_utils/search_constant_type.hh Wed May 09 23:00:10 2012 +0100
@@ -168,12 +168,8 @@
/************************/
void *visit(neg_time_c *symbol);
void *visit(duration_c *symbol);
+ void *visit(interval_c *symbol);
void *visit(fixed_point_c *symbol);
- void *visit(days_c *symbol);
- void *visit(hours_c *symbol);
- void *visit(minutes_c *symbol);
- void *visit(seconds_c *symbol);
- void *visit(milliseconds_c *symbol);
/************************************/
/* B 1.2.3.2 - Time of day and Date */
--- a/absyntax_utils/type_initial_value.cc Wed May 09 22:59:10 2012 +0100
+++ b/absyntax_utils/type_initial_value.cc Wed May 09 23:00:10 2012 +0100
@@ -84,7 +84,7 @@
date_literal_0 = new date_literal_c(integer_1, integer_1, integer_1);
date_literal_0 = new date_literal_c(new integer_c("1970"), integer_1, integer_1);
daytime_literal_0 = new daytime_c(integer_0, integer_0, real_0);
- time_0 = new duration_c(new time_type_name_c(), NULL, new seconds_c(integer_0, NULL)); // T#0S
+ time_0 = new duration_c(new time_type_name_c(), NULL, new interval_c(NULL, NULL, NULL, integer_0, NULL)); // T#0s
date_0 = new date_c(new date_type_name_c(), date_literal_0); // D#0001-01-01
tod_0 = new time_of_day_c(new tod_type_name_c(), daytime_literal_0); // TOD#00:00:00
dt_0 = new date_and_time_c(new dt_type_name_c(), date_literal_0, daytime_literal_0); // DT#0001-01-01-00:00:00
--- a/stage1_2/iec_bison.yy Wed May 09 22:59:10 2012 +0100
+++ b/stage1_2/iec_bison.yy Wed May 09 23:00:10 2012 +0100
@@ -58,6 +58,17 @@
/**********************************************************************/
/**********************************************************************/
+/* NOTE: the following file contains many rules used merely for detecting errors in
+ * the IEC source code being parsed.
+ * To remove all these rules, simply execute the command (first replace all '%' with '/'):
+ * $sed '\:%\* ERROR_CHECK_BEGIN \*%:,\:%\* ERROR_CHECK_END \*%: d' iec_bison.yy
+ *
+ * The above command had to be edited ('/' replaced by '%') so as not to include the C syntax that closes
+ * comments inside this comment!
+ * If you place the command in a shell script, be sure to remove the backslashes '\' before each asterisk '*' !!
+ */
+
+
@@ -490,17 +501,6 @@
%type <leaf> seconds
%type <leaf> milliseconds
-%type <leaf> integer_d
-%type <leaf> integer_h
-%type <leaf> integer_m
-%type <leaf> integer_s
-%type <leaf> integer_ms
-%type <leaf> fixed_point_d
-%type <leaf> fixed_point_h
-%type <leaf> fixed_point_m
-%type <leaf> fixed_point_s
-%type <leaf> fixed_point_ms
-
%token <ID> fixed_point_token
%token <ID> fixed_point_d_token
%token <ID> integer_d_token
@@ -512,7 +512,8 @@
%token <ID> integer_s_token
%token <ID> fixed_point_ms_token
%token <ID> integer_ms_token
-
+%token <ID> end_interval_token
+%token <ID> erroneous_interval_token
// %token TIME
%token T_SHARP
@@ -2138,156 +2139,56 @@
{$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'TIME' and interval in duration."); yynerrs++;}
| TIME '-' interval
{$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'TIME' and interval in duration."); yynerrs++;}
-| TIME '#' error
- {$$ = NULL;
- if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for duration.");}
- else {print_err_msg(locf(@3), locl(@3), "invalid value for duration."); yyclearin;}
- yyerrok;
- }
-| T_SHARP error
- {$$ = NULL;
- if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no value defined for duration.");}
- else {print_err_msg(locf(@2), locl(@2), "invalid value for duration."); yyclearin;}
- yyerrok;
- }
-/* ERROR_CHECK_END */
-;
+| TIME '#' erroneous_interval_token
+ {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid value for duration."); yynerrs++;}
+| T_SHARP erroneous_interval_token
+ {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid value for duration."); yynerrs++;}
+| TIME '#' '-' erroneous_interval_token
+ {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid value for duration."); yynerrs++;}
+| T_SHARP '-' erroneous_interval_token
+ {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid value for duration."); yynerrs++;}
+/* ERROR_CHECK_END */
+;
+
+fixed_point:
+ integer
+| fixed_point_token {$$ = new fixed_point_c($1, locloc(@$));};
interval:
- days
-| hours
-| minutes
-| seconds
-| milliseconds
-;
-
-integer_d: integer_d_token {$$ = new integer_c($1, locloc(@$));};
-integer_h: integer_h_token {$$ = new integer_c($1, locloc(@$));};
-integer_m: integer_m_token {$$ = new integer_c($1, locloc(@$));};
-integer_s: integer_s_token {$$ = new integer_c($1, locloc(@$));};
-integer_ms: integer_ms_token {$$ = new integer_c($1, locloc(@$));};
-
-fixed_point_d:
- fixed_point_d_token
- {$$ = new fixed_point_c($1, locloc(@$));}
-| integer_d
-;
-
-fixed_point_h:
- fixed_point_h_token
- {$$ = new fixed_point_c($1, locloc(@$));}
-| integer_h
-;
-
-fixed_point_m:
- fixed_point_m_token
- {$$ = new fixed_point_c($1, locloc(@$));}
-| integer_m
-;
-
-fixed_point_s:
- fixed_point_s_token
- {$$ = new fixed_point_c($1, locloc(@$));}
-| integer_s
-;
-
-fixed_point_ms:
- fixed_point_ms_token
- {$$ = new fixed_point_c($1, locloc(@$));}
-| integer_ms
-;
-
-
-fixed_point:
- fixed_point_token
- {$$ = new fixed_point_c($1, locloc(@$));}
-| integer
-;
-
-
-days:
-/* fixed_point ('d') */
- fixed_point_d
- {$$ = new days_c($1, NULL, locloc(@$));}
-/*| integer ('d') ['_'] hours */
-| integer_d hours
- {$$ = new days_c($1, $2, locloc(@$));}
-| integer_d '_' hours
- {$$ = new days_c($1, $3, locloc(@$));}
-/* ERROR_CHECK_BEGIN */
-| integer_d '_' error
- {$$ = NULL;
- if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for hours in duration.");}
- else {print_err_msg(locf(@3), locl(@3), "invalid value for hours in duration."); yyclearin;}
- yyerrok;
- }
-/* ERROR_CHECK_END */
-;
-
-
-hours:
-/* fixed_point ('h') */
- fixed_point_h
- {$$ = new hours_c($1, NULL, locloc(@$));}
-/*| integer ('h') ['_'] minutes */
-| integer_h minutes
- {$$ = new hours_c($1, $2, locloc(@$));}
-| integer_h '_' minutes
- {$$ = new hours_c($1, $3, locloc(@$));}
-/* ERROR_CHECK_BEGIN */
-| integer_h '_' error
- {$$ = NULL;
- if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for minutes in duration.");}
- else {print_err_msg(locf(@3), locl(@3), "invalid value for minutes in duration."); yyclearin;}
- yyerrok;
- }
-/* ERROR_CHECK_END */
-
-;
-
-minutes:
-/* fixed_point ('m') */
- fixed_point_m
- {$$ = new minutes_c($1, NULL, locloc(@$));}
-/*| integer ('m') ['_'] seconds */
-| integer_m seconds
- {$$ = new minutes_c($1, $2, locloc(@$));}
-| integer_m '_' seconds
- {$$ = new minutes_c($1, $3, locloc(@$));}
-/* ERROR_CHECK_BEGIN */
-| integer_m '_' error
- {$$ = NULL;
- if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for seconds in duration.");}
- else {print_err_msg(locf(@3), locl(@3), "invalid value for seconds in duration."); yyclearin;}
- yyerrok;
- }
-/* ERROR_CHECK_END */
-;
-
-seconds:
-/* fixed_point ('s') */
- fixed_point_s
- {$$ = new seconds_c($1, NULL, locloc(@$));}
-/*| integer ('s') ['_'] milliseconds */
-| integer_s milliseconds
- {$$ = new seconds_c($1, $2, locloc(@$));}
-| integer_s '_' milliseconds
- {$$ = new seconds_c($1, $3, locloc(@$));}
-/* ERROR_CHECK_BEGIN */
-| integer_s '_' error
- {$$ = NULL;
- if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for milliseconds in duration.");}
- else {print_err_msg(locf(@3), locl(@3), "invalid value for milliseconds in duration."); yyclearin;}
- yyerrok;
- }
-/* ERROR_CHECK_END */
-;
-
-milliseconds:
-/* fixed_point ('ms') */
- fixed_point_ms
- {$$ = new milliseconds_c($1, locloc(@$));}
+ days hours minutes seconds milliseconds end_interval_token
+ {$$ = new interval_c($1, $2, $3, $4, $5, locloc(@$));};
+;
+
+
+days: /* fixed_point ('d') */
+ /* empty */ {$$ = NULL;}
+| fixed_point_d_token {$$ = new fixed_point_c($1, locloc(@$));};
+| integer_d_token {$$ = new integer_c($1, locloc(@$));};
+;
+
+hours: /* fixed_point ('h') */
+ /* empty */ {$$ = NULL;}
+| fixed_point_h_token {$$ = new fixed_point_c($1, locloc(@$));};
+| integer_h_token {$$ = new integer_c($1, locloc(@$));};
+;
+
+minutes: /* fixed_point ('m') */
+ /* empty */ {$$ = NULL;}
+| fixed_point_m_token {$$ = new fixed_point_c($1, locloc(@$));};
+| integer_m_token {$$ = new integer_c($1, locloc(@$));};
+;
+
+seconds: /* fixed_point ('s') */
+ /* empty */ {$$ = NULL;}
+| fixed_point_s_token {$$ = new fixed_point_c($1, locloc(@$));};
+| integer_s_token {$$ = new integer_c($1, locloc(@$));};
+;
+
+milliseconds: /* fixed_point ('ms') */
+ /* empty */ {$$ = NULL;}
+| fixed_point_ms_token {$$ = new fixed_point_c($1, locloc(@$));};
+| integer_ms_token {$$ = new integer_c($1, locloc(@$));};
;
@@ -2985,13 +2886,18 @@
{$$ = new array_initial_elements_list_c(locloc(@$)); $$->add_element($1);}
| array_initial_elements_list ',' array_initial_elements
{$$ = $1; $$->add_element($3);}
-/* ERROR_CHECK_BEGIN
+/* ERROR_CHECK_BEGIN */
+/* The following error checking rules have been commented out. Why? Was it a typo?
+ * Lets keep them commented out for now...
+ */
+/*
| array_initial_elements_list ',' error
{$$ = $1;
if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no array initial value in array initial values list.");}
else {print_err_msg(locf(@3), locl(@3), "invalid array initial value in array initial values list."); yyclearin;}
yyerrok;
}
+*/
/* ERROR_CHECK_END */
;
@@ -3145,7 +3051,11 @@
{$$ = new structure_element_initialization_list_c(locloc(@$)); $$->add_element($1);}
| structure_element_initialization_list ',' structure_element_initialization
{$$ = $1; $$->add_element($3);}
-/* ERROR_CHECK_BEGIN
+/* ERROR_CHECK_BEGIN */
+/* The following error checking rules have been commented out. Why? Was it a typo?
+ * Lets keep them commented out for now...
+ */
+/*
| structure_element_initialization_list structure_element_initialization
{$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in structure element initialization list in structure initialization."); yynerrs++;}
| structure_element_initialization_list ',' error
@@ -3154,6 +3064,7 @@
else {print_err_msg(locf(@3), locl(@3), "invalid structure element initialization in structure initialization."); yyclearin;}
yyerrok;
}
+*/
/* ERROR_CHECK_END */
;
@@ -5454,12 +5365,15 @@
{$$ = NULL;}
| '(' {cmd_goto_sfc_priority_state();} PRIORITY {cmd_pop_state();} ASSIGN integer ')'
{$$ = $6;}
-/* ERROR_CHECK_BEGIN
+/* ERROR_CHECK_BEGIN */
+/* The following error checking rules have been intentionally commented out. */
+/*
| '(' ASSIGN integer ')'
{$$ = NULL; print_err_msg(locl(@1), locf(@2), "'PRIORITY' missing between '(' and ':=' in transition declaration with priority."); yynerrs++;}
| '(' error ASSIGN integer ')'
{$$ = NULL; print_err_msg(locf(@2), locl(@2), "expecting 'PRIORITY' between '(' and ':=' in transition declaration with priority."); yyerrok;}
- ERROR_CHECK_END */
+*/
+/* ERROR_CHECK_END */
;
@@ -8250,6 +8164,7 @@
}
/* first parse the standard library file... */
+ /* Do not debug the standard library, even if debug flag is set! */
/*
#if YYDEBUG
yydebug = 1;
--- a/stage1_2/iec_flex.ll Wed May 09 22:59:10 2012 +0100
+++ b/stage1_2/iec_flex.ll Wed May 09 23:00:10 2012 +0100
@@ -91,8 +91,10 @@
*/
%option noyy_top_state
-/* We will not be using unput() in our flex code... */
+/* We will be using unput() in our flex code, so we cannot set the following option!... */
+/*
%option nounput
+*/
/**************************************************/
/* External Variable and Function declarations... */
@@ -241,6 +243,10 @@
%{
/* return all the text in the current token back to the input stream. */
void unput_text(unsigned int n);
+/* return all the text in the current token back to the input stream,
+ * but first return to the stream an additional character to mark the end of the token.
+ */
+void unput_and_mark(const char c);
%}
@@ -340,6 +346,16 @@
* expecting any action qualifiers, flex does not return these tokens, and is free
* to interpret them as previously defined variables/functions/... as the case may be.
*
+ * The time_literal_state is required because TIME# literals are decomposed into
+ * portions, and wewant to send these portions one by one to bison. Each poertion will
+ * represent the value in days/hours/minutes/seconds/ms.
+ * Unfortunately, some of these portions may also be lexically analysed as an identifier. So,
+ * we need to disable lexical identification of identifiers while parsing TIME# literals!
+ * e.g.: TIME#55d_4h_56m
+ * We would like to return to bison the tokens 'TIME' '#' '55d' '_' '4h' '_' '56m'
+ * Unfortunately, flex will join '_' and '4h' to create a legal {identifier} '_4h',
+ * and return that identifier instead! So, we added this state!
+ *
* The state machine has 7 possible states (INITIAL, config, decl, body, st, il, sfc)
* Possible state changes are:
* INITIAL -> goto(decl_state)
@@ -418,7 +434,8 @@
/* we are parsing sfc code, and expecting the priority token. */
%s sfc_priority_state
-
+/* we are parsing a TIME# literal. We must not return any {identifier} tokens. */
+%x time_literal_state
/*******************/
@@ -598,6 +615,15 @@
/* B.1.2.1 Numeric literals */
/******************************/
integer {digit}((_?{digit})*)
+
+/* Some helper symbols for parsing TIME literals... */
+integer_0_59 (0(_?))*([0-5](_?))?{digit}
+integer_0_19 (0(_?))*([0-1](_?))?{digit}
+integer_20_23 (0(_?))*2(_?)[0-3]
+integer_0_23 {integer_0_19}|{integer_20_23}
+integer_0_999 {digit}((_?{digit})?)((_?{digit})?)
+
+
binary_integer 2#{bit}((_?{bit})*)
bit [0-1]
octal_integer 8#{octal_digit}((_?{octal_digit})*)
@@ -673,21 +699,54 @@
/************************/
fixed_point {integer}\.{integer}
-fixed_point_d {fixed_point}d
-integer_d {integer}d
-
-fixed_point_h {fixed_point}h
-integer_h {integer}h
-
-fixed_point_m {fixed_point}m
-integer_m {integer}m
-
-fixed_point_s {fixed_point}s
-integer_s {integer}s
-
-fixed_point_ms {fixed_point}ms
-integer_ms {integer}ms
-
+
+/* NOTE: The IEC 61131-3 v2 standard has an incorrect formal syntax definition of duration,
+ * as its definition does not match the standard's text.
+ * IEC 61131-3 v3 (committee draft) seems to have this fixed, so we use that
+ * definition instead!
+ *
+ * duration::= ('T' | 'TIME') '#' ['+'|'-'] interval
+ * interval::= days | hours | minutes | seconds | milliseconds
+ * fixed_point ::= integer [ '.' integer]
+ * days ::= fixed_point 'd' | integer 'd' ['_'] [ hours ]
+ * hours ::= fixed_point 'h' | integer 'h' ['_'] [ minutes ]
+ * minutes ::= fixed_point 'm' | integer 'm' ['_'] [ seconds ]
+ * seconds ::= fixed_point 's' | integer 's' ['_'] [ milliseconds ]
+ * milliseconds ::= fixed_point 'ms'
+ *
+ *
+ * The original IEC 61131-3 v2 definition is:
+ * duration ::= ('T' | 'TIME') '#' ['-'] interval
+ * interval ::= days | hours | minutes | seconds | milliseconds
+ * fixed_point ::= integer [ '.' integer]
+ * days ::= fixed_point 'd' | integer 'd' ['_'] hours
+ * hours ::= fixed_point 'h' | integer 'h' ['_'] minutes
+ * minutes ::= fixed_point 'm' | integer 'm' ['_'] seconds
+ * seconds ::= fixed_point 's' | integer 's' ['_'] milliseconds
+ * milliseconds ::= fixed_point 'ms'
+
+ */
+
+interval_ms_X ({integer_0_999}(\.{integer})?)ms
+interval_s_X {integer_0_59}s(_?{interval_ms_X})?
+interval_m_X {integer_0_59}m(_?{interval_s_X})?
+interval_h_X {integer_0_23}h(_?{interval_m_X})?
+
+interval_ms {integer}ms|({fixed_point}ms)
+interval_s {integer}s(_?{interval_ms_X})?|({fixed_point}s)
+interval_m {integer}m(_?{interval_s_X})?|({fixed_point}m)
+interval_h {integer}h(_?{interval_m_X})?|({fixed_point}h)
+interval_d {integer}d(_?{interval_h_X})?|({fixed_point}d)
+
+interval {interval_ms}|{interval_s}|{interval_m}|{interval_h}|{interval_d}
+
+/* to help provide nice error messages, we also parse an incorrect but plausible interval... */
+/* NOTE that this erroneous interval will be parsed outside the time_literal_state, so must not
+ * be able to parse any other legal lexcial construct (besides a legal interval, but that
+ * is OK as this rule will appear _after_ the rule to parse legal intervals!).
+ */
+fixed_point_or_integer {fixed_point}|{integer}
+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)?
/********************************************/
/* B.1.4.1 Directly Represented Variables */
@@ -719,9 +778,9 @@
* in which case we are currently using "%I3" as the variable
* name.
*/
-direct_variable_matplc %{identifier}
-
-direct_variable {direct_variable_standard}|{direct_variable_matplc}
+/* direct_variable_matplc %{identifier} */
+/* direct_variable {direct_variable_standard}|{direct_variable_matplc} */
+direct_variable {direct_variable_standard}
/******************************************/
/* B 1.4.3 - Declaration & Initialisation */
@@ -1541,23 +1600,26 @@
/* B 1.2.3.1 - Duration */
/************************/
{fixed_point} {yylval.ID=strdup(yytext); return fixed_point_token;}
-
-{fixed_point_d} {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_d_token;}
-{integer_d} {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_d_token;}
-
-{fixed_point_h} {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_h_token;}
-{integer_h} {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_h_token;}
-
-{fixed_point_m} {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_m_token;}
-{integer_m} {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_m_token;}
-
-{fixed_point_s} {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_s_token;}
-{integer_s} {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_s_token;}
-
-{fixed_point_ms} {yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return fixed_point_ms_token;}
-{integer_ms} {yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return integer_ms_token;}
-
-
+{interval} {/*fprintf(stderr, "entering time_literal_state ##%s##\n", yytext);*/ unput_and_mark('#'); yy_push_state(time_literal_state);}
+{erroneous_interval} {return erroneous_interval_token;}
+
+<time_literal_state>{
+{integer}d {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_d_token;}
+{integer}h {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_h_token;}
+{integer}m {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_m_token;}
+{integer}s {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_s_token;}
+{integer}ms {yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return integer_ms_token;}
+{fixed_point}d {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_d_token;}
+{fixed_point}h {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_h_token;}
+{fixed_point}m {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_m_token;}
+{fixed_point}s {yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_s_token;}
+{fixed_point}ms {yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return fixed_point_ms_token;}
+
+_ /* do nothing - eat it up!*/
+\# {/*fprintf(stderr, "poping from time_literal_state (###)\n");*/ yy_pop_state(); return end_interval_token;}
+. {ERROR;}
+\n {ERROR;}
+}
/*******************************/
/* B.1.2.2 Character Strings */
/*******************************/
@@ -1645,6 +1707,20 @@
}
+/* return all the text in the current token back to the input stream,
+ * but first return to the stream an additional character to mark the end of the token.
+ */
+void unput_and_mark(const char c) {
+ char *yycopy = strdup( yytext ); /* unput() destroys yytext, so we copy it first */
+ unput(c);
+ for (int i = yyleng-1; i >= 0; i--)
+ unput(yycopy[i]);
+
+ free(yycopy);
+}
+
+
+
/* Called by flex when it reaches the end-of-file */
int yywrap(void)
{
--- a/stage4/generate_c/generate_c.cc Wed May 09 22:59:10 2012 +0100
+++ b/stage4/generate_c/generate_c.cc Wed May 09 23:00:10 2012 +0100
@@ -353,6 +353,10 @@
unsigned long long get_time(void) {return time;};
+ /* NOTE: we should really remove this function, and replace it with extract_integer_value() (in absyntax_utils.h)
+ * but right now I don't want to spend time checking if this change will introduce some conversion bug
+ * since it returns a long long, and not a float!
+ */
void *get_integer_value(token_c *token) {
std::string str = "";
for (unsigned int i = 0; i < strlen(token->value); i++)
@@ -362,6 +366,10 @@
return NULL;
}
+ /* NOTE: this function is incomplete, as it should also be removing '_' inserted into the literal,
+ * but we leave it for now.
+ * In truth, we should really have an extract_real_value() in absyntax_util.h !!!
+ */
void *get_float_value(token_c *token) {
current_value = atof(token->value);
return NULL;
@@ -388,48 +396,31 @@
/* SYM_TOKEN(fixed_point_c) */
void *visit(fixed_point_c *symbol) {return get_float_value(symbol);}
- /* SYM_REF2(days_c, days, hours) */
- void *visit(days_c *symbol) {
- if (symbol->hours)
- symbol->hours->accept(*this);
- symbol->days->accept(*this);
- time += (unsigned long long)(current_value * 24 * 3600 * SECOND);
- return NULL;
- }
-
- /* SYM_REF2(hours_c, hours, minutes) */
- void *visit(hours_c *symbol) {
- if (symbol->minutes)
- symbol->minutes->accept(*this);
- symbol->hours->accept(*this);
- time += (unsigned long long)(current_value * 3600 * SECOND);
- return NULL;
- }
-
- /* SYM_REF2(minutes_c, minutes, seconds) */
- void *visit(minutes_c *symbol) {
- if (symbol->seconds)
- symbol->seconds->accept(*this);
- symbol->minutes->accept(*this);
+
+ /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */
+ void *visit(interval_c *symbol) {
+ current_value = 0;
+ if (NULL != symbol->milliseconds) symbol->milliseconds->accept(*this);
+ time += (unsigned long long)(current_value * MILLISECOND);
+
+ current_value = 0;
+ if (NULL != symbol->seconds) symbol->seconds->accept(*this);
+ time += (unsigned long long)(current_value * SECOND);
+
+ current_value = 0;
+ if (NULL != symbol->minutes) symbol->minutes->accept(*this);
time += (unsigned long long)(current_value * 60 * SECOND);
- return NULL;
- }
-
- /* SYM_REF2(seconds_c, seconds, milliseconds) */
- void *visit(seconds_c *symbol) {
- if (symbol->milliseconds)
- symbol->milliseconds->accept(*this);
- symbol->seconds->accept(*this);
- time += (unsigned long long)(current_value * SECOND);
- return NULL;
- }
-
- /* SYM_REF2(milliseconds_c, milliseconds, unused) */
- void *visit(milliseconds_c *symbol) {
- symbol->milliseconds->accept(*this);
- time += (unsigned long long)(current_value * MILLISECOND);
- return NULL;
- }
+
+ current_value = 0;
+ if (NULL != symbol->hours) symbol->hours->accept(*this);
+ time += (unsigned long long)(current_value * 60 * 60 * SECOND);
+
+ current_value = 0;
+ if (NULL != symbol->days) symbol->days->accept(*this);
+ time += (unsigned long long)(current_value * 60 * 60 * 24 * SECOND);
+
+ return NULL;
+ }
};
/***********************************************************************/
@@ -791,7 +782,7 @@
/* signed_integer DOTDOT signed_integer */
//SYM_REF2(subrange_c, lower_limit, upper_limit)
void *visit(subrange_c *symbol) {
- int dimension = extract_integer(symbol->upper_limit) - extract_integer(symbol->lower_limit) + 1;
+ int dimension = extract_integer_value(symbol->upper_limit) - extract_integer_value(symbol->lower_limit) + 1;
switch (current_mode) {
case arrayname_im:
current_array_name += "_";
--- a/stage4/generate_c/generate_c_base.cc Wed May 09 22:59:10 2012 +0100
+++ b/stage4/generate_c/generate_c_base.cc Wed May 09 23:00:10 2012 +0100
@@ -410,18 +410,12 @@
void *visit(duration_c *symbol) {
TRACE("duration_c");
s4o.print("__time_to_timespec(");
- if (NULL == symbol->neg)
- s4o.print("1"); /* positive time value */
- else
- symbol->neg->accept(*this); /* this will print '-1' :-) */
-
- s4o.print(", ");
-
+
+ if (NULL == symbol->neg) s4o.print("1"); /* positive time value */
+ else symbol->neg->accept(*this); /* this will print '-1' :-) */
+
+ s4o.print(", ");
symbol->interval->accept(*this);
- if (typeid(*symbol->interval) == typeid(hours_c)) {s4o.print(", 0");}
- if (typeid(*symbol->interval) == typeid(minutes_c)) {s4o.print(", 0, 0");}
- if (typeid(*symbol->interval) == typeid(seconds_c)) {s4o.print(", 0, 0, 0");}
- if (typeid(*symbol->interval) == typeid(milliseconds_c)) {s4o.print(", 0, 0, 0, 0");}
s4o.print(")");
return NULL;
}
@@ -430,73 +424,32 @@
/* SYM_TOKEN(fixed_point_c) */
void *visit(fixed_point_c *symbol) {return print_striped_token(symbol);}
-
-/* SYM_REF2(days_c, days, hours) */
-void *visit(days_c *symbol) {
- TRACE("days_c");
- if (NULL == symbol->hours)
- s4o.print("0, 0, 0, 0"); /* milliseconds, seconds, minutes, hours */
- else
- symbol->hours->accept(*this);
-
- s4o.print(", ");
-
- symbol->days->accept(*this);
- return NULL;
-}
-
-
-/* SYM_REF2(hours_c, hours, minutes) */
-void *visit(hours_c *symbol) {
- TRACE("hours_c");
- if (NULL == symbol->minutes)
- s4o.print("0, 0, 0"); /* milliseconds, seconds, minutes */
- else
- symbol->minutes->accept(*this);
-
- s4o.print(", ");
-
- symbol->hours->accept(*this);
- return NULL;
-}
-
-
-/* SYM_REF2(minutes_c, minutes, seconds) */
-void *visit(minutes_c *symbol) {
- TRACE("minutes_c");
- if (NULL == symbol->seconds)
- s4o.print("0, 0"); /* milliseconds, seconds */
- else
- symbol->seconds->accept(*this);
-
- s4o.print(", ");
-
- symbol->minutes->accept(*this);
- return NULL;
-}
-
-
-/* SYM_REF2(seconds_c, seconds, milliseconds) */
-void *visit(seconds_c *symbol) {
- TRACE("seconds_c");
- if (NULL == symbol->milliseconds)
- s4o.print("0"); /* milliseconds */
- else
- symbol->milliseconds->accept(*this);
-
- s4o.print(", ");
-
- symbol->seconds->accept(*this);
- return NULL;
-}
-
-
-/* SYM_REF2(milliseconds_c, milliseconds, unused) */
-void *visit(milliseconds_c *symbol) {
- TRACE("milliseconds_c");
- symbol->milliseconds->accept(*this);
- return NULL;
-}
+/* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */
+void *visit(interval_c *symbol) {
+ TRACE("interval_c");
+ /* s4o.print("0, 0, 0, 0, 0"); // milliseconds, seconds, minutes, hours, days */
+ if (NULL == symbol->milliseconds) s4o.print("0"); /* milliseconds */
+ else symbol->milliseconds->accept(*this);
+ s4o.print(", ");
+
+ if (NULL == symbol->seconds) s4o.print("0"); /* seconds */
+ else symbol->seconds->accept(*this);
+ s4o.print(", ");
+
+ if (NULL == symbol->minutes) s4o.print("0"); /* minutes */
+ else symbol->minutes->accept(*this);
+ s4o.print(", ");
+
+ if (NULL == symbol->hours) s4o.print("0"); /* hours */
+ else symbol->hours->accept(*this);
+ s4o.print(", ");
+
+ if (NULL == symbol->days) s4o.print("0"); /* days */
+ else symbol->days->accept(*this);
+
+ return NULL;
+}
+
/************************************/
/* B 1.2.3.2 - Time of day and Date */
--- a/stage4/generate_c/generate_c_typedecl.cc Wed May 09 22:59:10 2012 +0100
+++ b/stage4/generate_c/generate_c_typedecl.cc Wed May 09 23:00:10 2012 +0100
@@ -255,7 +255,7 @@
case array_td:
if (current_basetypedeclaration == arraysubrange_bd) {
s4o_incl.print("[");
- dimension = extract_integer(symbol->upper_limit) - extract_integer(symbol->lower_limit) + 1;
+ dimension = extract_integer_value(symbol->upper_limit) - extract_integer_value(symbol->lower_limit) + 1;
print_integer_incl(dimension);
s4o_incl.print("]");
}
--- a/stage4/generate_c/generate_c_vardecl.cc Wed May 09 22:59:10 2012 +0100
+++ b/stage4/generate_c/generate_c_vardecl.cc Wed May 09 23:00:10 2012 +0100
@@ -211,7 +211,7 @@
/* signed_integer DOTDOT signed_integer */
//SYM_REF2(subrange_c, lower_limit, upper_limit)
void *visit(subrange_c *symbol) {
- int dimension = extract_integer(symbol->upper_limit) - extract_integer(symbol->lower_limit) + 1;
+ int dimension = extract_integer_value(symbol->upper_limit) - extract_integer_value(symbol->lower_limit) + 1;
switch (current_mode) {
case arraysize_am:
array_size *= dimension;
@@ -264,7 +264,7 @@
switch (current_mode) {
case initializationvalue_am:
- initial_element_number = extract_integer(symbol->integer);
+ initial_element_number = extract_integer_value(symbol->integer);
if (current_initialization_count < defined_values_count) {
int temp_element_number = 0;
int diff = defined_values_count - current_initialization_count;
@@ -1407,7 +1407,7 @@
/* signed_integer DOTDOT signed_integer */
//SYM_REF2(subrange_c, lower_limit, upper_limit)
void *visit(subrange_c *symbol) {
- int dimension = extract_integer(symbol->upper_limit) - extract_integer(symbol->lower_limit) + 1;
+ long long dimension = extract_integer_value(symbol->upper_limit) - extract_integer_value(symbol->lower_limit) + 1;
s4o.print("_");
print_integer(dimension);
return NULL;
--- a/stage4/generate_iec/generate_iec.cc Wed May 09 22:59:10 2012 +0100
+++ b/stage4/generate_iec/generate_iec.cc Wed May 09 23:00:10 2012 +0100
@@ -234,43 +234,37 @@
void *visit(fixed_point_c *symbol) {return print_token(symbol);}
-void *visit(days_c *symbol) {
- symbol->days->accept(*this);
- s4o.print("d");
- if (symbol->hours != NULL)
+/* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */
+void *visit(interval_c *symbol) {
+ if (NULL != symbol->days) {
+ symbol->days->accept(*this);
+ s4o.print("d");
+ }
+
+ if (NULL != symbol->hours) {
symbol->hours->accept(*this);
- return NULL;
-}
-
-void *visit(hours_c *symbol) {
- symbol->hours->accept(*this);
- s4o.print("h");
- if (symbol->minutes != NULL)
+ s4o.print("h");
+ }
+
+ if (NULL != symbol->minutes) {
symbol->minutes->accept(*this);
- return NULL;
-}
-
-void *visit(minutes_c *symbol) {
- symbol->minutes->accept(*this);
- s4o.print("m");
- if (symbol->seconds != NULL)
+ s4o.print("m");
+ }
+
+ if (NULL != symbol->seconds) {
symbol->seconds->accept(*this);
- return NULL;
-}
-
-void *visit(seconds_c *symbol) {
- symbol->seconds->accept(*this);
- s4o.print("s");
- if (symbol->milliseconds != NULL)
+ s4o.print("s");
+ }
+
+ if (NULL != symbol->milliseconds) {
symbol->milliseconds->accept(*this);
- return NULL;
-}
-
-void *visit(milliseconds_c *symbol) {
- symbol->milliseconds->accept(*this);
- s4o.print("ms");
- return NULL;
-}
+ s4o.print("ms");
+ }
+
+ return NULL;
+}
+
+
/************************************/
/* B 1.2.3.2 - Time of day and Date */