Browse Source

Arvore binaria de strings, variaveis e constantes.

Waldemar Celes 31 years ago
parent
commit
1c749a3059
2 changed files with 237 additions and 0 deletions
  1. 210 0
      tree.c
  2. 27 0
      tree.h

+ 210 - 0
tree.c

@@ -0,0 +1,210 @@
+/*
+** tree.c
+** TecCGraf - PUC-Rio
+*/
+ 
+char *rcs_tree="$Id: $";
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "lua.h"
+#include "tree.h"
+
+
+#define lua_strcmp(a,b)	(a[0]<b[0]?(-1):(a[0]>b[0]?(1):strcmp(a,b))) 
+
+
+typedef struct TreeNode
+{
+ struct TreeNode *right;
+ struct TreeNode *left;
+ Word            index;
+ char            str[1];        /* \0 byte already reserved */
+} TreeNode;
+
+static TreeNode *string_root = NULL;
+static TreeNode *constant_root = NULL;
+static TreeNode *variable_root = NULL;
+
+/*
+** Insert a new string/constant/variable at the tree. 
+*/
+static char *tree_create (TreeNode **node, char *str)
+{
+ if (*node == NULL)
+ {
+  *node = (TreeNode *) malloc (sizeof(TreeNode)+strlen(str));
+  if (*node == NULL)
+   lua_error ("memoria insuficiente\n");
+  (*node)->left = (*node)->right = NULL;
+  strcpy((*node)->str, str);
+  (*node)->index = UNMARKED_STRING;
+  return (*node)->str;
+ }
+ else
+ {
+  int c = lua_strcmp(str, (*node)->str);
+  if (c < 0) 
+   return tree_create(&(*node)->left, str);
+  else if (c > 0)
+   return tree_create(&(*node)->right, str);
+  else
+   return (*node)->str;
+ }
+}
+
+char *lua_strcreate (char *str) 
+{
+ return tree_create(&string_root, str);
+}
+
+char *lua_constcreate (char *str) 
+{
+ return tree_create(&constant_root, str);
+}
+
+char *lua_varcreate (char *str) 
+{
+ return tree_create(&variable_root, str);
+}
+
+
+
+/*
+** Free a node of the tree
+*/
+static TreeNode *lua_strfree (TreeNode *parent)
+{
+ if (parent->left == NULL && parent->right == NULL) /* no child */
+ {
+  free (parent);
+  return NULL;
+ }
+ else if (parent->left == NULL)         /* only right child */
+ {
+  TreeNode *p = parent->right;
+  free (parent);
+  return p;
+ }
+ else if (parent->right == NULL)        /* only left child */
+ {
+  TreeNode *p = parent->left;
+  free (parent);
+  return p;
+ }
+ else                                   /* two children */
+ {
+  TreeNode *p = parent, *r = parent->right;
+  while (r->left != NULL)
+  {
+   p = r;
+   r = r->left;
+  }
+  if (p == parent)
+  {
+   r->left  = parent->left;
+   parent->left = NULL;
+   parent->right = r->right;
+   r->right = lua_strfree(parent);
+  }
+  else
+  {
+   TreeNode *t = r->right;
+   r->left  = parent->left;
+   r->right = parent->right;
+   parent->left = NULL;
+   parent->right = t;
+   p->left  = lua_strfree(parent);
+  }
+  return r;
+ }
+}
+
+/*
+** Traverse tree for garbage collection
+*/
+static TreeNode *lua_travcollector (TreeNode *r)
+{
+ if (r == NULL) return NULL;
+ r->right = lua_travcollector(r->right);
+ r->left  = lua_travcollector(r->left);
+ if (r->index == UNMARKED_STRING) 
+  return lua_strfree(r);
+ else
+ {
+  r->index = UNMARKED_STRING;
+  return r;
+ }
+}
+
+
+/*
+** Garbage collection function.
+** This function traverse the tree freening unindexed strings
+*/
+void lua_strcollector (void)
+{
+ string_root = lua_travcollector(string_root);
+}
+
+/*
+** Return next variable.
+*/
+static TreeNode *tree_next (TreeNode *node, char *str)
+{
+#if 0
+ if (node == NULL) return NULL;
+ if (str == NULL || lua_strcmp(str, node->str) < 0)
+ {
+  TreeNode *result = tree_next(node->left, str);
+  return result == NULL ? node : result;
+ }
+ else
+ {
+  return tree_next(node->right, str);
+ }
+#else
+ if (node == NULL) return NULL;
+ else if (str == NULL) return node;
+ else
+ {
+  int c = lua_strcmp(str, node->str);
+  if (c == 0)
+   return node->left != NULL ? node->left : node->right;
+  else if (c < 0)
+  {
+   TreeNode *result = tree_next(node->left, str);
+   return result != NULL ? result : node->right;
+  }
+  else
+   return tree_next(node->right, str);
+ }
+#endif
+}
+
+char *lua_varnext (char *n)
+{
+ TreeNode *result = tree_next(variable_root, n);
+ return result != NULL ? result->str : NULL;
+}
+
+
+/*
+** Given an id, find the string with exaustive search
+*/
+static char *tree_name (TreeNode *node, Word index)
+{
+ if (node == NULL) return NULL;
+ if (node->index == index) return node->str;
+ else
+ {
+  char *result = tree_name(node->left, index);
+  return result != NULL ? result : tree_name(node->right, index);
+ }
+}
+char *lua_varname (Word index)
+{
+ return tree_name(variable_root, index);
+}

+ 27 - 0
tree.h

@@ -0,0 +1,27 @@
+/*
+** tree.h
+** TecCGraf - PUC-Rio
+** $Id: $
+*/
+
+#ifndef tree_h
+#define tree_h
+
+#include "opcode.h"
+
+
+#define UNMARKED_STRING	0xFFFF
+#define MARKED_STRING   0xFFFE
+#define MAX_WORD        0xFFFD
+
+#define indexstring(s) (*(((Word *)s)-1))
+
+
+char *lua_strcreate    (char *str);
+char *lua_constcreate  (char *str);
+char *lua_varcreate    (char *str);
+void  lua_strcollector (void);
+char *lua_varnext      (char *n);
+char *lua_varname      (Word index);
+
+#endif