Пример #1
0
void patch_symbol_table(ast_node root, symhashtable_t *symtable){

  symhashtable_t *hashtable;
  symnode_t *snode = NULL;

  switch(root->node_type){

    case ID_N:

      hashtable = find_hashtable(symtable, root->curr_level, root->curr_sib);
      if(hashtable != NULL){
        //snode = lookup_symhashtable(hashtable, root->value_string, NOHASHSLOT);
        assert(hashtable != NULL);
        assert(snode == NULL);
        for(;hashtable != NULL && snode == NULL; hashtable = hashtable->parent) {
          snode = lookup_symhashtable(hashtable, root->value_string, NOHASHSLOT);
        }
        if(snode != NULL){
          if(snode->type == VAR_ARRAY_INT_T && root->left_child == NULL){
            root->return_type = ARRAY_TYPE_N;
//           root->node_type = ARRAY_TYPE_N; // change in the future
          }
        }
      break;

    case ARRAY_TYPE_N:
      hashtable = find_hashtable(symtable, root->curr_level, root->curr_sib);
      if(hashtable != NULL){
        snode = lookup_symhashtable(hashtable, root->value_string, NOHASHSLOT);
        if(snode != NULL){
          if(snode->type == VAR_INT_T){
            snode->type = VAR_ARRAY_INT_T;
          }
        }
      }
      break;

    default:
      break;
    }
  }


  ast_node child;

  for(child = root->left_child; child != NULL; child = child->right_sibling){
    patch_symbol_table(child, symtable);
  }
}
Пример #2
0
/* 
 * lookup_in_symboltable
 *
 * Lookup an entry in a symbol table.  If found return a pointer to it.
 * Otherwise, return NULL 
 */
symnode_t *lookup_in_symboltable(symboltable_t  *symtab, char *name, var_type vType) {
  symnode_t *node;
  symhashtable_t *hashtable;


  assert(symtab);

  int base_len = strlen(name);
  // Account for potential prefix and null termination
  char *typed_name = calloc(1, sizeof(char) * (base_len + 3)); 

  switch(vType) {
    case TEMP_VT :
      sprintf(typed_name, "%s%s", temp_prefix, name);
      break;

    case CONST_VT :
      sprintf(typed_name, "%s%s", constant_prefix, name);
      break;

    default :
      free(typed_name);
      typed_name = name;
  }

  for (node = NULL, hashtable = symtab->leaf;
       (node == NULL) &&  (hashtable != NULL);
       hashtable = hashtable->parent) {
    node = lookup_symhashtable(hashtable, typed_name, NOHASHSLOT);
  }

  return node;
}
Пример #3
0
/*
 * Function to check if a particular variable or function identifier
 * has been redefined.
 */
int check_if_redef(ast_node anode, symboltable_t *symtab ,int lvl, int sibno) {
  symhashtable_t *hash = find_hashtable(symtab->root, lvl, sibno);

  /* If scope with (lvl, sibno) identifier could be found, start search */
  if(hash != NULL) {
    /* node = NULL in case we don't find anything */
    symnode_t *node = NULL;
    node = lookup_symhashtable(hash, anode->value_string, NOHASHSLOT);

    /* Found a match in current or parent scope? */
    if(node != NULL){
      /* If abstract syntax node has a type, it was previously defined */
      if(anode->return_type != ROOT_N && anode->isDecl == 1) {
        symtabError = 1;
        if(anode->node_type == FUNC_DECLARATION_N) {
          fprintf(stderr, "line: %d | error: redefinition of function %s\n", anode->line_num ,anode->value_string);
        }
        if(anode->node_type == ID_N || anode->node_type == ARRAY_TYPE_N) {
          fprintf(stderr, "line: %d | error: redefinition of identifier %s\n", anode->line_num ,anode->value_string);
        }

        return 0;
      }
    }
  }
  /* Not found */
  return 1;
}
Пример #4
0
/* 
 * instert_into_symboltable
 *
 * Insert an entry into the innermost scope of symbol table.  First 
 * make sure it's not already in that scope.  Return a pointer to the
 * entry. 
 */
symnode_t *insert_into_symboltable(symboltable_t *symtab, var_lookup_type type, char *name, int lineno) {

  assert(symtab);
  assert(symtab->leaf);
  
  symnode_t *node = lookup_symhashtable(symtab->leaf, name, NOHASHSLOT);

  /* error check!! */
  
  if (node == NULL) {
    node = insert_into_symhashtable(symtab->leaf, type, name, lineno, LOCAL_VT);
    return node;
  } else {
    return NULL;
  }
   
}
Пример #5
0
symnode_t *insert_temp(symboltable_t *symtab, var_lookup_type type, char *name, int lineno) {

  assert(symtab);
  assert(symtab->leaf);

  int name_len = strlen(name);
  char *typed_name = calloc(1, sizeof(char) * (name_len + 3));
  sprintf(typed_name, "%s%s", temp_prefix, name);

  symnode_t *node = lookup_symhashtable(symtab->leaf, typed_name, NOHASHSLOT);

  if (node == NULL) {
    node = insert_into_symhashtable(symtab->root, type, typed_name, lineno, TEMP_VT);
    return node;
  } else {
    return NULL;
  }
}
Пример #6
0
/* Insert a new entry into a symhashtable, but only if it is not
   already present. */
symnode_t *insert_into_symhashtable(symhashtable_t *hashtable, var_lookup_type type, char *name, int lineno, var_type vType) {

  assert(hashtable);

  int slot = hashPJW(name, hashtable->size);
  symnode_t *node = lookup_symhashtable(hashtable, name, slot);

  /* error check if node already existed! */

  if (node == NULL) {
    node = create_symnode(name, type, hashtable, lineno);
    node->vType = vType;
    node->next = hashtable->table[slot];
    hashtable->table[slot] = node;
  }

  return node;
}
Пример #7
0
/* Insert an entry into the innermost scope of symbol table.  First
   make sure it's not already in that scope.  Return a pointer to the
   entry. */
  symnode_t *insert_into_symboltable(symboltable_t *symtab, ast_node astnode) {

    char *name = astnode->value_string;
    assert(symtab);
    assert(symtab->leaf);

    symnode_t *node = lookup_symhashtable(symtab->leaf, name, NOHASHSLOT);

    /* error check!! */

    if (node == NULL) {
      node = insert_into_symhashtable(symtab->leaf, astnode);
      return node;
    } else {
      return NULL;
    }

  }
Пример #8
0
/*
 * Checks if a particular variable has already been declared.
 */
  int check_if_declared(ast_node anode, symboltable_t *symtab ,int lvl, int sibno) {

    symhashtable_t *hash = find_hashtable(symtab->root, lvl, sibno);

    assert(hash != NULL);
    assert(anode != NULL);

    /* Set node to NULL so that, if no match is found, it will be NULL and we can
     * act accordingly.
     */
    symnode_t *node = NULL;

    /*
     * Recurse up until hash table with matching identifier, or the root, is found.
     */
    for(;hash != NULL && node == NULL; hash = hash->parent) {
      node = lookup_symhashtable(hash, anode->value_string, NOHASHSLOT);
    }

    /* If not found, variable or function is undeclared. */
    if(node == NULL) {
      symtabError = 1;
      if(anode->node_type == FUNCTION_N) {
        fprintf(stderr, "line: %d | error: use of undeclared function %s\n", anode->line_num, anode->value_string);
      }
      else if(anode->node_type == ID_N || anode->node_type == ARRAY_TYPE_N) {
        fprintf(stderr, "line: %d | error: use of undeclared identifier %s\n", anode->line_num, anode->value_string);
      }

      return 0;
    }
    else { /* Otherwise, declaration for variable or function has been found */
      return 1;
    }

  }
Пример #9
0
/* Looks up a node in a symhashtable without knowing the hashslot */
symnode_t *lookup_in_symhashtable(symhashtable_t *hashtable, char *name) {
  return lookup_symhashtable(hashtable, name, NOHASHSLOT);
}
Пример #10
0
void link_ast_to_symnode(ast_node root, symboltable_t *symtab) {
  symhashtable_t *hash = NULL;
  symnode_t *snode = NULL;

  /* Depending on node types, go deeper, create sibling scopes, add to hashtable,
   * or take other appropriate action.
   */
  switch (root->node_type) {
    case SEQ_N:     // change main level when see a new sequence
      break;

    case FORMAL_PARAMS_N:
      break;

    case FUNC_DECLARATION_N: // function declaraions
      break;

    case FUNCTION_N:
      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      assert(hash != NULL);
      for(;hash != NULL && snode == NULL; hash = hash->parent) {
        snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(snode != NULL);
      root->snode = snode;
      break;

    case ID_N:      /* print the id */
      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      assert(hash != NULL);
      for(;hash != NULL && snode == NULL; hash = hash->parent) {
        snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(snode != NULL);
      root->snode = snode;
      break;

    case ARRAY_TYPE_N:             // check for return types!
      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      assert(hash != NULL);
      for(;hash != NULL && snode == NULL; hash = hash->parent) {
        snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(snode != NULL);
      root->snode = snode;
      break;

    case INT_LITERAL_N:
      hash = symtab->literal_collection;
      assert(hash != NULL);
      assert(root->value_string != NULL);
      snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      root->snode = snode;
      break;

    case STRING_LITERAL_N:
      hash = symtab->literal_collection;
      assert(hash != NULL);
      assert(root->value_string != NULL);
      snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      root->snode = snode;
      break;

    case RETURN_N:

      hash = symtab->literal_collection;
      assert(hash != NULL);
      if(root->left_child->node_type == VOID_TYPE_N){
        snode = lookup_symhashtable(hash, root->left_child->value_string, NOHASHSLOT);
        root->left_child->snode = snode;
      }
      break;


    default:
      break;
  }

/* Recurse on each child of the subtree root */
  ast_node child;
  for (child = root->left_child; child != NULL; child = child->right_sibling)
    link_ast_to_symnode(child, symtab);
}
Пример #11
0
void collect_literals(ast_node root, symboltable_t *symtab){

  ast_node child;
  symnode_t *node;
  symhashtable_t *collection = symtab->literal_collection;
  assert(collection != NULL);
  char* name;
  int slot = 0;

  /* Recursively call the function to traverse the tree in a preorder way */
  for(child = root->left_child; child != NULL; child = child->right_sibling){
    collect_literals(child, symtab);
  }

  switch (root->node_type) {
    case STRING_LITERAL_N:
      name = root->value_string;

      // Calculate slot for this node, try to find the current node in the symbol table
      slot = hashPJW(name, collection->size);
      node = lookup_symhashtable(collection, name, slot);

      if(node == NULL){
        insert_into_symhashtable(collection, root);
      }

      break;

    /* Need to hash the value differently so as to not to mistake strings and
    ints, (e.g. 1 vs "1") */
    case INT_LITERAL_N:

      name = calloc(DEFAULTSTRSIZE, sizeof(char));
      sprintf(name, "__%d", root->value_int);
      root->value_string = strdup(name);

      slot = hashPJW(name, collection->size);
      node = lookup_symhashtable(collection, name, slot);

      if(node == NULL){
        insert_into_symhashtable(collection, root);
      }
      break;

    case RETURN_N:
      // Empty return. Create a new symnode to add to
      // the collection because otherwise it will give us
      // trouble later when trying to create quads, since
      // the function to create quads takes symnodes and there
      // is currently no symnode for this empty return.

      if(root->left_child != NULL){
        if(root->left_child->node_type == VOID_TYPE_N){
          name = calloc(DEFAULTSTRSIZE, sizeof(char));
          sprintf(name, "__%s", "void");

          root->left_child->value_string = calloc(DEFAULTSTRSIZE, sizeof(char));
          strcpy(root->left_child->value_string, name);

          slot = hashPJW(name, collection->size);
          node = lookup_symhashtable(collection, name, slot);

          if(node == NULL){
            insert_into_symhashtable(collection, root->left_child);
          }
        }
      }
    default:
      break;
  }
}
Пример #12
0
/*declaration of func and identifiers is already checked during  build_symbol_table
* so here, we just check for paramter inputs into functions
*/
int check_function(ast_node root, symboltable_t *symtab) {
  symhashtable_t *hash = NULL;
  symnode_t *node = NULL;
  ast_node anode = NULL;

  switch (root->node_type) {

    case FUNCTION_N:
        hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
        for(;hash != NULL && node == NULL; hash = hash->parent) {
          node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
          //node is the original declaration stored in symbol table
        }
        assert(node != NULL); //as hashtable was built previously, it must be found for func_n

        // Count the number of parameters passed to the function
        int i = 0;
        for(anode = root->left_child; anode != NULL; anode = anode->right_sibling) {
          i++;
        }

        if(node->num_parameters != i) {
          funcError = 1;
          fprintf(stderr, "line: %d | Error: Number of parameters to function %s does not match number of parameters in declaration at line %d\n",
          root->line_num, root->value_string, root->line_declared);
        }
        else {
          int k = 0;
          for(anode = root->left_child; anode != NULL; anode = anode->right_sibling) {
            if(!((anode->return_type == INT_TYPE_N && node->parameters[k] == VAR_INT_T) ||
             (anode->return_type == ARRAY_TYPE_N && node->parameters[k] == VAR_ARRAY_INT_T)) ) {

            // if(!(anode->return_type == INT_TYPE_N && node->parameters[k] == VAR_INT_T)) {
              funcError = 1;
              //printf("\n\n  parm type is: %s return_type is: %s \n\n", TYPE_NAME(node->parameters[k]), NODE_NAME(anode->return_type));
              // fprintf(stderr, "\n\n %s return_type: %s but should be %s \n\n",anode->value_string ,NODE_NAME(anode->return_type), TYPE_NAME(node->parameters[k]));
              assert(anode != NULL);
              //assert(anode->snode
              //assert(anode->snode);
              fprintf(stderr, "%dth param. Expecting  %s, got (%s, %s)\n",
                k, TYPE_NAME(node->parameters[k]), NODE_NAME(anode->return_type), NODE_NAME(anode->node_type));
              //fprintf(stderr, "snode of ^ is %s ", anode->snode->name);
              fprintf(stderr, "line: %d | Error: Input parameters to function %s do not match the declaration at line %d\n",
                root->line_num, root->value_string, root->line_declared);
              return 1;
            }
            k++;
          }
        }
      break;



    default:
      // printf("at default of switch\n");
      assert(symtab->root != NULL);
      break;


  }

  /* Recurse on each child of the subtree root, with a depth one
     greater than the root's depth. */
  ast_node child;
  for (child = root->left_child; child != NULL; child = child->right_sibling)
    check_function(child, symtab);
  return 0;
}
Пример #13
0
/*
* Works on an assumption that build hashtable as already been run. (i.e. no errors generated from building hashtable)
*/
void record_var_type_in_ast(ast_node root, symboltable_t *symtab) {
  symhashtable_t *hash = NULL;
  symnode_t *node = NULL;


  /* Depending on node types, go deeper, create sibling scopes, add to hashtable,
   * or take other appropriate action.
   */
  switch (root->node_type) {

    case FUNC_DECLARATION_N:
        hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
        for(;hash != NULL && node == NULL; hash = hash->parent) {
          node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
        }
        assert(node != NULL); //as hashtable was built prev, it must be found for func_n
        if(node->type == FUNC_VOID_T) {
          root->return_type = VOID_TYPE_N;
        } else if(node->type == FUNC_INT_T) {
          root->return_type = INT_TYPE_N;
        }
        root->line_declared = node->abnode->line_num;
      break;

    case FUNCTION_N: //all function_n nodes are calls not declarations
        hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
        for(;hash != NULL && node == NULL; hash = hash->parent) {
          node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
        }
        assert(node != NULL); //as hashtable was built prev, it must be found for func_n
        if(node->type == FUNC_VOID_T) {
          root->return_type = VOID_TYPE_N;
        } else if(node->type == FUNC_INT_T) {
          root->return_type = INT_TYPE_N;
        }
        root->line_declared = node->abnode->line_num;
      break;

    case ID_N:

      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      assert(hash != NULL);
      for(;hash != NULL && node == NULL; hash = hash->parent) {
          //printf("  \n\n value string is %s\n\n", root->value_string);
        node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(node != NULL); //as hashtable was built prev, it must be found for ID_N

      if(root->return_type == 0) {  // a zero value means that it is not a declaration, since only declarations
                                    // are assigned a return type when building the abstract syntax tree.
        if(node->type == VAR_INT_T) {
          root->return_type = INT_TYPE_N;
        }
      }
      root->line_declared = node->abnode->line_num;
      break;

    case ARRAY_TYPE_N:             // check for return types!
      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      for(;hash != NULL && node == NULL; hash = hash->parent) {
        node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(node != NULL); //as hashtable was built prev, it must be found for array_type_n
      if(root->return_type == 0) {
        if(node->type == VAR_ARRAY_INT_T){
          if(root->left_child == NULL){
            root->return_type = ARRAY_TYPE_N;
          }
          else{
            root->return_type = INT_TYPE_N;
          }
        }

      }
      root->line_declared = node->abnode->line_num;
      break;

    case INT_LITERAL_N:
      root->return_type = INT_TYPE_N;
      break;

    case RETURN_N: //not sure if we deal with this here...
      assert(symtab->root != NULL);
      break;

    default:
      // printf("at default of switch\n");
      assert(symtab->root != NULL);

      break;
  }


  /* Recurse on each child of the subtree root, with a depth one */
  ast_node child;
  for (child = root->left_child; child != NULL; child = child->right_sibling)
    record_var_type_in_ast(child, symtab);
}
Пример #14
0
/* Insert a new entry into a symhashtable, but only if it is not
   already present. Return*/
  symnode_t *insert_into_symhashtable(symhashtable_t *hashtable, ast_node astnode) {

    char* name = astnode->value_string;

    assert(hashtable);

    int slot = hashPJW(name, hashtable->size);
    symnode_t *node = lookup_symhashtable(hashtable, name, slot);

  /* error check if node already existed! */
   if (node == NULL) {

      node = create_symnode(name, hashtable);

      node->abnode = astnode;
      astnode->snode = node;

      if(astnode->node_type == INT_LITERAL_N){
        node->num_val = astnode->value_int;
      }

      if(astnode->node_type == ARRAY_TYPE_N) {
        if(astnode->left_child != NULL ){
          astnode->array_length = astnode->left_child->value_int;
          node->array_length = astnode->array_length;
        }
      }

      if(astnode->node_type == STRING_LITERAL_N){
        node->type = STRING_T;
      }

      if(astnode->node_type == FUNC_DECLARATION_N) {
      //printf("FUNC_DEC detected!");
        if(astnode->return_type == INT_TYPE_N) {
          node->type = FUNC_INT_T;
          //printf(" %s\n", TYPE_NAME(node->type));
        }
        else if(astnode->return_type == VOID_TYPE_N) {
          node->type = FUNC_VOID_T;
          //printf(" %s\n", TYPE_NAME(node->type));
        }

        ast_node anode;
        int i = 0;
        assert(astnode->left_child != NULL);

        for(anode = astnode->left_child->left_child; anode != NULL; anode = anode->right_sibling) {
          i++;
        }

        node->num_parameters = i;
        node->parameters = calloc(sizeof(decl_type), i);
        assert(node->parameters);

        i = 0;

        for(anode = astnode->left_child->left_child; anode != NULL; anode = anode->right_sibling) {
          if(anode->return_type == INT_TYPE_N) {
            node->parameters[i] = VAR_INT_T;
          }
          else if(anode->return_type == ARRAY_TYPE_N){
            node->parameters[i] = VAR_ARRAY_INT_T;
          }
          i++;
        }
      }

      else if(astnode->node_type == ID_N) {
        //printf("VAR detected!");
        if(astnode->return_type == INT_TYPE_N) {
          node->type = VAR_INT_T;
          //printf(" %s\n", TYPE_NAME(node->type));
        }
      }
      else if(astnode->node_type == ARRAY_TYPE_N){
        if(astnode->return_type == INT_TYPE_N) {
          node->type = VAR_ARRAY_INT_T;
          //printf(" %s\n", TYPE_NAME(node->type));
        }
      }

      node->next = hashtable->table[slot];
      hashtable->table[slot] = node;
    }
    else{
      if(node->abnode->node_type == ARRAY_TYPE_N || node->abnode->return_type == ARRAY_TYPE_N) {
        node->abnode->array_length = node->array_length;
      }
    }

    return node;
  }