diff -r bfbe4aca6b77 -r 9b61eb4f00dc absyntax_utils/search_base_type.cc --- a/absyntax_utils/search_base_type.cc Tue Nov 13 18:02:15 2012 +0000 +++ b/absyntax_utils/search_base_type.cc Tue Nov 13 18:03:17 2012 +0000 @@ -54,7 +54,7 @@ -search_base_type_c::search_base_type_c(void) {current_type_name = NULL;} +search_base_type_c::search_base_type_c(void) {current_type_name = NULL; current_basetype = NULL;} /* static method! */ void search_base_type_c::create_singleton(void) { @@ -66,15 +66,17 @@ symbol_c *search_base_type_c::get_basetype_decl(symbol_c *symbol) { create_singleton(); if (NULL == symbol) return NULL; + search_base_type_singleton->current_type_name = NULL; + search_base_type_singleton->current_basetype = NULL; return (symbol_c *)symbol->accept(*search_base_type_singleton); } /* static method! */ symbol_c *search_base_type_c::get_basetype_id (symbol_c *symbol) { create_singleton(); - if (NULL == symbol) return NULL; - + if (NULL == symbol) return NULL; search_base_type_singleton->current_type_name = NULL; + search_base_type_singleton->current_basetype = NULL; symbol->accept(*search_base_type_singleton); return (symbol_c *)search_base_type_singleton->current_type_name; } @@ -112,6 +114,10 @@ symbol_c *type_decl; this->current_type_name = type_name; + /* if we have reached this point, it is because the current_basetype is not yet pointing to the base datatype we are looking for, + * so we will be searching for the delcaration of the type named in type_name, which might be the base datatype (we search recursively!) + */ + this->current_basetype = NULL; /* look up the type declaration... */ type_decl = type_symtable.find_value(type_name); @@ -244,20 +250,37 @@ /* enumerated_type_name ':' enumerated_spec_init */ void *search_base_type_c::visit(enumerated_type_declaration_c *symbol) { this->current_type_name = symbol->enumerated_type_name; + /* NOTE: We want search_base_type_c to return a enumerated_type_declaration_c as the base datatpe if possible + * (i.e. if it is a named datatype declared inside a TYPE ... END_TYPE declarations, as opposed to an + * anonymous datatype declared in a VAR ... AND_VAR declaration). + * However, we cannot return this symbol just yet, as it may not be the final base datatype. + * So we store it in a temporary current_basetype variable! + */ + this->current_basetype = symbol; return symbol->enumerated_spec_init->accept(*this); } /* enumerated_specification ASSIGN enumerated_value */ void *search_base_type_c::visit(enumerated_spec_init_c *symbol) { this->is_enumerated = true; - return symbol->enumerated_specification->accept(*this); + // current_basetype may have been set in the previous enumerated_type_declaration_c visitor, in which case we do not want to overwrite the value! + if (NULL == this->current_basetype) + this->current_basetype = symbol; + /* NOTE: the following line may call either the visitor to + * - identifier_c, in which case this is not yet the base datatype we are looking for (it will set current_basetype to NULL!) + * - enumerated_value_list_c, in which case we have found the base datatype. + */ + return symbol->enumerated_specification->accept(*this); } /* helper symbol for enumerated_specification->enumerated_spec_init */ /* enumerated_value_list ',' enumerated_value */ void *search_base_type_c::visit(enumerated_value_list_c *symbol) { this->is_enumerated = true; - return (void *)symbol; + // current_basetype may have been set in the previous enumerated_type_declaration_c or enumerated_spec_init_c visitors, in which case we do not want to overwrite the value! + if (NULL == this->current_basetype) + this->current_basetype = symbol; + return (void *)current_basetype; } /* enumerated_type_name '#' identifier */