diff -r 000000000000 -r fb772792efd1 util/symtable.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/symtable.cc Wed Jan 31 15:32:38 2007 +0100 @@ -0,0 +1,199 @@ +/* + * (c) 2003 Mario de Sousa + * + * Offered to the public under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 IL and ST compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +/* + * A generic symbol table. + * + * This is used to create symbol tables such as a list of + * variables currently in scope, etc... + * Note that the list of previously defined funstions uses the + * dsymtable_c instead, as it requires the table to store duplicate values. + */ + + +#include +#include "symtable.hh" + + + +/* A macro for printing out internal parser errors... */ +#define ERROR error_exit(__FILE__,__LINE__) +/* function defined in main.cc */ +extern void error_exit(const char *file_name, int line_no); + + + + +template +symtable_c::symtable_c(void) {inner_scope = NULL;} + + + /* clear all entries... */ +template +void symtable_c::reset(void) { + _base.clear(); +} + + /* create new inner scope */ +template +void symtable_c::push(void) { + if (inner_scope != NULL) { + inner_scope->push(); + } else { + inner_scope = new symtable_c(); + } +} + + /* clear most inner scope */ + /* returns 1 if this is the inner most scope */ + /* 0 otherwise */ +template +int symtable_c::pop(void) { + if (inner_scope != NULL) { + if (inner_scope->pop() == 1) { + delete inner_scope; + inner_scope = NULL; + } + return 0; + } else { + _base.clear(); + return 1; + } +} + +template +void symtable_c::set(const symbol_c *symbol, value_t new_value) { + if (inner_scope != NULL) { + inner_scope->set(symbol, new_value); + return; + } + + const token_c *name = dynamic_cast(symbol); + if (name == NULL) + ERROR; + set(name->value, new_value); +} + + +template +void symtable_c::set(const char *identifier_str, value_t new_value) { + if (inner_scope != NULL) { + inner_scope->set(identifier_str, new_value); + return; + } + + // std::cout << "set_identifier(" << identifier_str << "): \n"; + iterator i = _base.find(identifier_str); + if (i == _base.end()) + /* identifier not already in map! */ + ERROR; + + _base[identifier_str] = new_value; +} + +template +void symtable_c::insert(const char *identifier_str, value_t new_value) { + if (inner_scope != NULL) { + inner_scope->insert(identifier_str, new_value); + return; + } + + // std::cout << "store_identifier(" << identifier_str << "): \n"; + std::pair new_element(identifier_str, new_value); + std::pair res = _base.insert(new_element); + if (!res.second) + /* error inserting new identifier... */ + /* identifier already in map? */ + ERROR; +} + +template +void symtable_c::insert(const symbol_c *symbol, value_t new_value) { +/* +// not required... + if (inner_scope != NULL) { + inner_scope->insert(symbol, new_value); + return; + } +*/ + const token_c *name = dynamic_cast(symbol); + if (name == NULL) + ERROR; + insert(name->value, new_value); +} + + + +/* returns null_value if not found! */ +template +value_type symtable_c::find_value(const char *identifier_str) { + if (inner_scope != NULL) { + value_t token = inner_scope->find_value(identifier_str); + if (token != null_value) + /* found in the lower level */ + return token; + } + + /* if no lower level, or not found in lower level... */ + iterator i = _base.find(identifier_str); + + if (i == _base.end()) + return null_value; + else + return i->second; +} + + +template +value_type symtable_c::find_value(const symbol_c *symbol) { + const token_c *name = dynamic_cast(symbol); + if (name == NULL) + ERROR; + return find_value(name->value); +} + + +/* debuging function... */ +template +void symtable_c::print(void) { + for(iterator i = _base.begin(); + i != _base.end(); + i++) + std::cout << i->second << ":" << i->first << "\n"; + std::cout << "=====================\n"; + + if (inner_scope != NULL) { + inner_scope->print(); + } +} + + + + + + + + +