stage4/generate_c/decompose_var_instance_name.cc
changeset 70 e1f0ebd2d9ec
child 98 d0cdf1d00b74
equal deleted inserted replaced
69:41cb5b80416e 70:e1f0ebd2d9ec
       
     1 /*
       
     2  * (c) 2003 Mario de Sousa
       
     3  *
       
     4  * Offered to the public under the terms of the GNU General Public License
       
     5  * as published by the Free Software Foundation; either version 2 of the
       
     6  * License, or (at your option) any later version.
       
     7  *
       
     8  * This program is distributed in the hope that it will be useful, but
       
     9  * WITHOUT ANY WARRANTY; without even the implied warranty of
       
    10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
       
    11  * Public License for more details.
       
    12  *
       
    13  * This code is made available on the understanding that it will not be
       
    14  * used in safety-critical situations without a full and competent review.
       
    15  */
       
    16 
       
    17 /*
       
    18  * An IEC 61131-3 IL and ST compiler.
       
    19  *
       
    20  * Based on the
       
    21  * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
       
    22  *
       
    23  */
       
    24 
       
    25 
       
    26 /* Decomposes a variable instance name into its constituents,
       
    27  * example:
       
    28  *    window.points[1].coordinate.x
       
    29  *
       
    30  *  will succesfully return
       
    31  *        - window
       
    32  *        - points
       
    33  *        - coordinate
       
    34  *        - x
       
    35  * on succesive calls to decompose_var_instance_name_c::next_part()
       
    36  */
       
    37 class decompose_var_instance_name_c: null_visitor_c {
       
    38 
       
    39   private:
       
    40     symbol_c *variable_name;
       
    41     symbol_c *next_variable_name;
       
    42     symbol_c *current_recursive_variable_name;
       
    43     symbol_c *previously_returned_variable_name;
       
    44 
       
    45   public:
       
    46     decompose_var_instance_name_c(symbol_c *variable_instance_name) {
       
    47       variable_name = variable_instance_name;
       
    48       next_variable_name = NULL;
       
    49       current_recursive_variable_name = NULL;
       
    50       previously_returned_variable_name = NULL;
       
    51     }
       
    52 
       
    53   public:
       
    54     symbol_c *next_part(void) {
       
    55       /* We must always start from the top!
       
    56        * See note in the structured_variable_c visitor
       
    57        * to understand why...
       
    58        */
       
    59       symbol_c *res = (symbol_c *)variable_name->accept(*this);
       
    60       next_variable_name = current_recursive_variable_name;
       
    61 
       
    62       if (previously_returned_variable_name == res)
       
    63         return NULL;
       
    64       previously_returned_variable_name = res;
       
    65       return res;
       
    66     }
       
    67 
       
    68   public:
       
    69 /*********************/
       
    70 /* B 1.4 - Variables */
       
    71 /*********************/
       
    72     void *visit(symbolic_variable_c *symbol) {return (void *)(symbol->var_name);}
       
    73 
       
    74 /********************************************/
       
    75 /* B.1.4.1   Directly Represented Variables */
       
    76 /********************************************/
       
    77     void *visit(direct_variable_c *symbol) {return (void *)symbol;}
       
    78 
       
    79 /*************************************/
       
    80 /* B.1.4.2   Multi-element Variables */
       
    81 /*************************************/
       
    82 /*  subscripted_variable '[' subscript_list ']' */
       
    83 // SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
       
    84     void *visit(array_variable_c *symbol) {
       
    85       /* NOTE: the subscripted_variable may itself be a structure!,
       
    86        * so we must recursevily visit!
       
    87        */
       
    88       return symbol->subscripted_variable->accept(*this);
       
    89     }
       
    90 
       
    91 /*  record_variable '.' field_selector */
       
    92 /*  WARNING: input and/or output variables of function blocks
       
    93  *           may be accessed as fields of a tructured variable!
       
    94  *           Code handling a structured_variable_c must take
       
    95  *           this into account!
       
    96  */
       
    97 //SYM_REF2(structured_variable_c, record_variable, field_selector)
       
    98     void *visit(structured_variable_c *symbol) {
       
    99       /* NOTE: The following code will not work, as structured_variable_c
       
   100        *       are grouped on the left, and not on the right!
       
   101        *
       
   102        *       example: window.origin.x
       
   103        *       will result in
       
   104        *       s1 = structured_variable_c("window, "origin");
       
   105        *       s2 = structured_variable_c(s1, "x");
       
   106        *       AND NOT
       
   107        *       s1 = structured_variable_c("origin", "x");
       
   108        *       s2 = structured_variable_c("window", s1);
       
   109        *
       
   110        *       as the following code assumes!!
       
   111        *
       
   112       current_variable_name = symbol->field_selector;
       
   113       return symbol->record_variable->accept(*this);
       
   114        */
       
   115 
       
   116       /* The correct code, is therefore more complex... */
       
   117       if (next_variable_name == symbol) {
       
   118         /* NOTE: field_selector is always an identifier_c,
       
   119 	 * so we do not have to recursevily visit it again...
       
   120 	 * return (void *)symbol->field_selector->accept(*this);  -> NOT REQUIRED!!
       
   121 	 */
       
   122 	return (void *)symbol->field_selector;
       
   123       }
       
   124 
       
   125       current_recursive_variable_name = symbol;
       
   126       return symbol->record_variable->accept(*this);
       
   127     }
       
   128 };
       
   129 
       
   130 
       
   131 
       
   132