Пример #1
0
ast_t* ast_get_case(ast_t* ast, const char* name, sym_status_t* status)
{
  // Same as ast_get, but is partially case insensitive. That is, type names
  // are compared as uppercase and other symbols are compared as lowercase.
  if(status != NULL)
    *status = SYM_NONE;

  do
  {
    if(ast->symtab != NULL)
    {
      sym_status_t status2;
      ast_t* value = (ast_t*)symtab_find_case(ast->symtab, name, &status2);

      if((status != NULL) && (*status == SYM_NONE))
        *status = status2;

      if(value != NULL)
        return value;
    }

    ast = ast->parent;
  } while((ast != NULL) && (token_get_id(ast->t) != TK_PROGRAM));

  return NULL;
}
Пример #2
0
static size_t length(ast_t* ast, size_t indent, bool type)
{
  size_t len = (indent * in_len) + strlen(token_print(ast->t));
  ast_t* child = ast->child;

  if(type || (child != NULL) || (ast->type != NULL))
    len += 2;

  switch(token_get_id(ast->t))
  {
    case TK_STRING: len += 6; break;
    case TK_ID: len += 5; break;
    default: {}
  }

  if(ast->symtab != NULL)
    len += 6;

  while(child != NULL)
  {
    len += 1 + length(child, 0, false);
    child = child->sibling;
  }

  if(ast->type != NULL)
    len += 1 + length(ast->type, 0, true);

  return len;
}
Пример #3
0
ast_t* ast_nearest(ast_t* ast, token_id id)
{
  while((ast != NULL) && (token_get_id(ast->t) != id))
    ast = ast->parent;

  return ast;
}
Пример #4
0
ast_t* ast_get(ast_t* ast, const char* name, sym_status_t* status)
{
  // Searches all parent scopes, but not the program scope, because the name
  // space for paths is separate from the name space for all other IDs.
  // If called directly on the program scope, searches it.
  if(status != NULL)
    *status = SYM_NONE;

  do
  {
    if(ast->symtab != NULL)
    {
      sym_status_t status2;
      ast_t* value = (ast_t*)symtab_find(ast->symtab, name, &status2);

      if((status != NULL) && (*status == SYM_NONE))
        *status = status2;

      if(value != NULL)
        return value;
    }

    ast = ast->parent;
  } while((ast != NULL) && (token_get_id(ast->t) != TK_PROGRAM));

  return NULL;
}
Пример #5
0
static void print_token(FILE* fp, token_t* token)
{
  switch(token_get_id(token))
  {
    case TK_STRING:
      fprintf(fp, "\"\"\"%s\"\"\"", token_print(token));
      break;

    case TK_ID:
      fprintf(fp, "(id %s)", token_print(token));
      break;

    default:
      fprintf(fp, "%s", token_print(token));
      break;
  }
}
Пример #6
0
ast_t* ast_token(token_t* t)
{
  ast_t* ast = POOL_ALLOC(ast_t);
  memset(ast, 0, sizeof(ast_t));
  ast->t = t;

  switch(token_get_id(t))
  {
  case TK_PROGRAM:
    ast->data = program_create();
    break;

  default:
    break;
  }

  return ast;
}
Пример #7
0
bool ast_all_consumes_in_scope(ast_t* outer, ast_t* inner, errorframe_t* errorf)
{
  ast_t* from = inner;
  bool ok = true;

  do
  {
    if(inner->symtab != NULL)
    {
      size_t i = HASHMAP_BEGIN;
      symbol_t* sym;

      while((sym = symtab_next(inner->symtab, &i)) != NULL)
      {
        // If it's consumed, and has a null value, it's from outside of this
        // scope. We need to know if it's outside the loop scope.
        if((sym->status == SYM_CONSUMED) && (sym->def == NULL))
        {
          if(!ast_within_scope(outer, inner, sym->name))
          {
            ast_t* def = ast_get(inner, sym->name, NULL);
            if(errorf != NULL)
            {
              ast_error_frame(errorf, from,
                "identifier '%s' is consumed when the loop exits", sym->name);
              ast_error_frame(errorf, def,
                "consumed identifier is defined here");
            }
            ok = false;
          }
        }
      }
    }

    if(inner == outer)
      break;

    inner = inner->parent;
  } while((inner != NULL) && (token_get_id(inner->t) != TK_PROGRAM));

  return ok;
}
Пример #8
0
static void fetch_next_lexer_token(parser_t* parser, bool free_prev_token)
{
  token_t* old_token = parser->token;
  token_t* new_token = lexer_next(parser->lexer);

  if(old_token != NULL)
    parser->last_token_line = token_line_number(old_token);

  if(old_token != NULL && token_get_id(new_token) == TK_EOF)
  {
    // Use location of last token for EOF to get better error reporting
    token_set_pos(new_token, token_source(old_token),
      token_line_number(old_token), token_line_position(old_token));
  }

  if(free_prev_token)
    token_free(old_token);

  parser->token = new_token;
}
Пример #9
0
bool ast_within_scope(ast_t* outer, ast_t* inner, const char* name)
{
  do
  {
    if(inner->symtab != NULL)
    {
      sym_status_t status2;
      ast_t* value = (ast_t*)symtab_find(inner->symtab, name, &status2);

      if(value != NULL)
        return true;
    }

    if(inner == outer)
      break;

    inner = inner->parent;
  } while((inner != NULL) && (token_get_id(inner->t) != TK_PROGRAM));

  return false;
}
Пример #10
0
static void print_token(FILE* fp, token_t* token)
{
  switch(token_get_id(token))
  {
    case TK_STRING:
    {
      char* escaped = token_print_escaped(token);
      fprintf(fp, "\"%s\"", escaped);
      ponyint_pool_free_size(strlen(escaped), escaped);
      break;
    }

    case TK_ID:
      fprintf(fp, "(id %s)", token_print(token));
      break;

    default:
      fprintf(fp, "%s", token_print(token));
      break;
  }
}
Пример #11
0
void ast_free(ast_t* ast)
{
  if(ast == NULL)
    return;

  ast_t* child = ast->child;
  ast_t* next;

  while(child != NULL)
  {
    next = child->sibling;
    ast_free(child);
    child = next;
  }

  ast_free(ast->type);

  switch(token_get_id(ast->t))
  {
    case TK_PROGRAM:
      program_free((program_t*)ast->data);
      break;

    case TK_PACKAGE:
      package_free((package_t*)ast->data);
      break;

    case TK_MODULE:
      source_close((source_t*)ast->data);
      break;

    default:
      break;
  }

  token_free(ast->t);
  symtab_free(ast->symtab);
  POOL_FREE(ast_t, ast);
}
Пример #12
0
// Get the next token ready for when we need it
static void get_next_token(build_parser_t* builder)
{
  assert(builder != NULL);

  if(builder->have_token)
    return;

  if(builder->token != NULL)
    token_free(builder->token);

  builder->token = lexer_next(builder->lexer);
  assert(builder->token != NULL);
  ast_token_id id;

  switch(token_get_id(builder->token))
  {
    case TK_LPAREN_NEW:
    case TK_LPAREN:     id = AT_LPAREN;  break;
    case TK_RPAREN:     id = AT_RPAREN;  break;
    case TK_LSQUARE_NEW:
    case TK_LSQUARE:    id = AT_LSQUARE; break;
    case TK_RSQUARE:    id = AT_RSQUARE; break;
    case TK_LBRACE:     id = AT_LBRACE;  break;
    case TK_RBRACE:     id = AT_RBRACE;  break;
    case TK_EOF:        id = AT_EOF;     break;
    case TK_LEX_ERROR:  id = AT_ERROR;   break;
    case TK_ID:         id = AT_ID;      break;
    case TK_STRING:     id = AT_STRING;  break;
    default:            id = AT_TOKEN;   break;
  }

  //printf("Got token %s %d -> %d\n", token_print(builder->token),
  //  token_get_id(builder->token), id);
  builder->id = id;
  builder->have_token = true;
  builder->line = token_line_number(builder->token);
  builder->pos = token_line_position(builder->token);
}
Пример #13
0
ast_t* ast_try_clause(ast_t* ast, size_t* clause)
{
  ast_t* last = NULL;

  while(ast != NULL)
  {
    switch(token_get_id(ast->t))
    {
      case TK_TRY:
      case TK_TRY_NO_CHECK:
      {
        *clause = ast_index(last);
        return ast;
      }

      default: {}
    }

    last = ast;
    ast = ast_parent(ast);
  }

  return NULL;
}
Пример #14
0
token_id ast_id(ast_t* ast)
{
  assert(ast != NULL);
  return token_get_id(ast->t);
}
Пример #15
0
static token_id current_token_id(parser_t* parser)
{
  return token_get_id(parser->token);
}