util/symtable.cc
changeset 0 fb772792efd1
child 279 c0453b7f99df
--- /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 <iostream>
+#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<typename value_type, value_type null_value>
+symtable_c<value_type, null_value>::symtable_c(void) {inner_scope = NULL;}
+
+
+ /* clear all entries... */
+template<typename value_type, value_type null_value>
+void symtable_c<value_type, null_value>::reset(void) {
+  _base.clear();
+}
+
+ /* create new inner scope */
+template<typename value_type, value_type null_value>
+void symtable_c<value_type, null_value>::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<typename value_type, value_type null_value>
+int symtable_c<value_type, null_value>::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<typename value_type, value_type null_value>
+void symtable_c<value_type, null_value>::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<const token_c *>(symbol);
+  if (name == NULL)
+    ERROR;
+  set(name->value, new_value);
+}
+
+
+template<typename value_type, value_type null_value>
+void symtable_c<value_type, null_value>::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<typename value_type, value_type null_value>
+void symtable_c<value_type, null_value>::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<const char *, value_t> new_element(identifier_str, new_value);
+  std::pair<iterator, bool> res = _base.insert(new_element);
+  if (!res.second)
+    /* error inserting new identifier... */
+    /* identifier already in map?        */
+    ERROR;
+}
+
+template<typename value_type, value_type null_value>
+void symtable_c<value_type, null_value>::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<const token_c *>(symbol);
+  if (name == NULL)
+    ERROR;
+  insert(name->value, new_value);
+}
+
+
+
+/* returns null_value if not found! */
+template<typename value_type, value_type null_value>
+value_type symtable_c<value_type, null_value>::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<typename value_type, value_type null_value>
+value_type symtable_c<value_type, null_value>::find_value(const symbol_c *symbol) {
+  const token_c *name = dynamic_cast<const token_c *>(symbol);
+  if (name == NULL)
+    ERROR;
+  return find_value(name->value);
+}
+
+
+/* debuging function... */
+template<typename value_type, value_type null_value>
+void symtable_c<value_type, null_value>::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();
+  }
+}
+
+
+
+
+
+
+
+
+