
// symbol tables

int lookahead_var() {
  return (lookahead() == integer_tok) &&
         ((triple_lookahead() == semi_colon_tok) ||
          (triple_lookahead() == open_bracket_tok));
}

int lookahead_procedure() {
  return (lookahead() == void_tok) &&
         (triple_lookahead() == open_paren_tok);
}

int lookahead_function() {
  return (lookahead() == integer_tok) &&
         (triple_lookahead() == open_paren_tok);
}

int is_relop(int token) {
  return (token == equal_tok) || (token == not_equals_tok)
    || (token == less_than_tok) || (token == greater_than_tok)
    || (token == less_or_equal_tok) || (token == greater_or_equal_tok);
}

int is_binary_operator(int token) {
  return ((token == assignment_tok) || (token == plus_tok)
          || (token == minus_tok) || (token == times_tok)
          || (token == div_tok)) || ((token == mod_tok)
                                     || (token == bit_and_tok)
                                     || (token == bit_or_tok)
                                     || (token == bit_xor_tok)
                                     || (token == shr_tok)
                                     || (token == shl_tok))
    || ((token == and_tok) || (token == or_tok) || (token == equal_tok)
        || (token == not_equals_tok)) || ((token == less_than_tok)
                                          || (token == greater_than_tok)
                                          || (token == less_or_equal_tok)
                                          || (token == greater_or_equal_tok));
}

int is_operator(int token) {
  return is_binary_operator(token) || (token == unary_minus_tok)
    || (token == bit_not_tok) || (token == not_tok);
}

int is_identifier(int token) {
  return !(is_operator(token)
           || ((token == semi_colon_tok) || (token == colon_tok)
               || (token == open_paren_tok) || (token == close_paren_tok))
           || ((token == open_bracket_tok) || (token == close_bracket_tok)
               || (token == period_tok) || (token == comma_tok)));
}

void log_sorted_vector(int first, int idx, int name, int sorted_name) {
  int i;
  int temp;
  int not_done;

  not_done = 1;
  i = idx - 1;
  while (not_done) {
    if (i < first)
      not_done = 0;
    else
    if (i == 0)
      not_done = 0;
    else
    if (stringeq(
      vector_ref(name, vector_ref(sorted_name, i)),
      vector_ref(name, vector_ref(sorted_name, i - 1)))
      == 1)
      not_done = 0;
    else {
      // swap
      temp = vector_ref(sorted_name, i - 1);
      vector_set(sorted_name, i - 1, vector_ref(sorted_name, i));
      vector_set(sorted_name, i, temp);
      i = i - 1;
    }
  }
    
  return;
}

// iterative binary search algorithm

int binary_search(
  int x, int left, int right, int name, int sorted_name) {
  int mid;
  int ret;
  int not_done;
  // assume not found
  ret = -1;
  not_done = 1;
  while (not_done)
    if (left <= right) {
      mid = ((right - left) >> 1) + left;
      if (stringeq(
        vector_ref(name, vector_ref(sorted_name, mid)),
        x) == 0) {
        // match
        not_done = 0;
        ret = vector_ref(sorted_name, mid);
      }
      else if (stringeq(
        x,
        vector_ref(name, vector_ref(sorted_name, mid)))
        == -1)
        // x < ...
        right = mid - 1;
      else
        left = mid + 1;
    }
    else
      not_done = 0;

  return ret;
}

int get_constant_value(int name) {
  int i;
  i = binary_search(name, 1, constant_idx - 1, constant_name, sorted_constant);
  if (i != -1)
    return i;
  else
    // not found
    return 0;
}

int is_function(int x) {
  int ret;
  ret =
    binary_search(
      x, 1, function_idx - 1, function_name, sorted_function);
  if (ret != -1) {
    global_found_function_idx = ret;
    global_annotation = ANNOTATION_FUNCTION;
    // TODO make this var local
    return ret;
  }
  else
    // not found
    return 0;
}

int is_procedure(int x) {
  int ret;
  ret =
    binary_search(
      x, 3, procedure_idx - 1, procedure_name, sorted_procedure);
  if (ret != -1) {
    global_annotation = ANNOTATION_PROCEDURE;
    // TODO make this var local
    return ret;
  }
  else
    // not found
    return 0;
}

int n_args(int token) {
  int i;
  i = is_function(token);
  if (i == 0) {
    i = is_procedure(token);
    return vector_ref(procedure_value, i);
  }
  else
    return vector_ref(function_value, i);
}

int find_top_level_var(int x) {
  int i;
  i =
    binary_search(
      x, 0, top_level_variable_idx - 1, top_level_variable_name,
      sorted_top_level_variable);
  if (i != -1)
    return vector_ref(top_level_variable_size, i);
  else
    // not found
    return 0;
}

int find_local_var(int x) {
  int i;
  int found;
  int done;
  i = 0;
  done = 0;
  found = 0;
  while (!done) {
    if (i == variable_idx)
      // not found
      done = 1;
    else if (stringeq(x, vector_ref(variable_name, i)) == 0) {
      // found
      done = 1;
      found = vector_ref(variable_size, i);
    }
    i = i + 1;
  }
  if (debug) {
    printf("local variable ");
    string_write(x);
    if (found != 0)
      printf(" found");
    else
      printf(" not found");
    writeln();
  }
  return found;
}

int find_local_var_offset(int x) {
  int i;
  int offset;
  int done;
  i = 0;
  done = 0;
  offset = 0;
  while (!done) {
    if (i == variable_idx)
      // not found
      done = 1;
    else if (stringeq(x, vector_ref(variable_name, i)) == 0) {
      // found
      done = 1;
      offset = vector_ref(variable_position, i);
    }
    i = i + 1;
  }
  return offset;
}

int local_variable_is_reference(int x) {
  int offset;
  // local vars are always size one so offset is index into reference table
  offset = find_local_var_offset(x);
  return (vector_ref(variable_is_reference, offset) == 1);
}
