Beispiel #1
0
ast_t* ast_from(ast_t* ast, token_id id)
{
  assert(ast != NULL);
  ast_t* new_ast = ast_token(token_dup_new_id(ast->t, id));
  set_scope_no_parent(new_ast, ast->parent);
  return new_ast;
}
Beispiel #2
0
static ast_t* duplicate(ast_t* parent, ast_t* ast)
{
  if(ast == NULL)
    return NULL;

  assert(ast_id(ast) != TK_PROGRAM && ast_id(ast) != TK_PACKAGE &&
    ast_id(ast) != TK_MODULE);

  ast_t* n = ast_token(token_dup(ast->t));
  n->data = ast->data;
  n->flags = ast->flags & AST_ALL_FLAGS;
  // We don't actually want to copy the orphan flag, but the following if
  // always explicitly sets or clears it.

  if(parent == NULL)
    set_scope_no_parent(n, ast->parent);
  else
    set_scope_and_parent(n, parent);

  n->child = duplicate(n, ast->child);
  n->type = duplicate(n, ast->type);

  if(ast->symtab != NULL)
    n->symtab = symtab_dup(ast->symtab);

  if(parent != NULL)
    n->sibling = duplicate(parent, ast->sibling);

  return n;
}
Beispiel #3
0
/* Load an ID node.
 * IDs are indicated by the keyword id followed by the ID name, all contained
 * within parentheses. For example:
 *    (id foo)
 *
 * The ( and id keyword must have been parsed before this is called.
 */
static ast_t* get_id(build_parser_t* builder, ast_t* existing_ast)
{
  assert(builder != NULL);

  if(existing_ast != NULL)
  {
    ast_free(existing_ast);
    build_error(builder, "Seen ID not first in node");
    return NULL;
  }

  ast_token_id id = get_token(builder);

  if(id != AT_ID && id != AT_STRING)
  {
    build_error(builder, "ID name expected");
    return NULL;
  }

  ast_t* ast = ast_token(builder->token);
  ast_setid(ast, TK_ID);
  save_token(builder);

  if(get_token(builder) != AT_RPAREN)
  {
    build_error(builder, "Close paren expected for ID");
    ast_free(ast);
    return NULL;
  }

  return ast;
}
Beispiel #4
0
static ast_t* consume_token(parser_t* parser)
{
  ast_t* ast = ast_token(parser->token);
  ast_setflag(ast, parser->next_flags);
  parser->next_flags = 0;
  fetch_next_lexer_token(parser, false);
  return ast;
}
Beispiel #5
0
ast_t* ast_from_float(ast_t* ast, double value)
{
  assert(ast != NULL);
  token_t* t = token_dup(ast->t);
  token_set_id(t, TK_FLOAT);
  token_set_float(t, value);

  ast_t* new_ast = ast_token(t);
  set_scope_no_parent(new_ast, ast->parent);
  return new_ast;
}
Beispiel #6
0
ast_t* ast_from_int(ast_t* ast, uint64_t value)
{
  assert(ast != NULL);
  token_t* t = token_dup(ast->t);
  token_set_id(t, TK_INT);

  lexint_t lexint = {value, 0};
  token_set_int(t, &lexint);

  ast_t* new_ast = ast_token(t);
  set_scope_no_parent(new_ast, ast->parent);
  return new_ast;
}
Beispiel #7
0
ast_t* ast_from_string(ast_t* ast, const char* name)
{
  if(name == NULL)
    return ast_from(ast, TK_NONE);

  token_t* t = token_dup(ast->t);
  token_set_id(t, TK_ID);
  token_set_string(t, name, 0);

  ast_t* new_ast = ast_token(t);
  set_scope_no_parent(new_ast, ast->parent);
  return new_ast;
}
Beispiel #8
0
// Process any deferred token we have
static void process_deferred_ast(parser_t* parser, rule_state_t* state)
{
  assert(parser != NULL);
  assert(state != NULL);

  if(state->deferred)
  {
    token_t* deferred_token = token_new(state->deferred_id);
    token_set_pos(deferred_token, parser->source, state->line, state->pos);
    state->ast = ast_token(deferred_token);
    state->deferred = false;
  }
}
Beispiel #9
0
ast_t* ast_blank(token_id id)
{
  return ast_token(token_new(id));
}
Beispiel #10
0
ast_t* ast_new(token_t* t, token_id id)
{
  return ast_token(token_dup_new_id(t, id));
}
Beispiel #11
0
// Load a sequence of nodes until the specified terminator is found
static ast_t* get_nodes(build_parser_t* builder, ast_token_id terminator)
{
  assert(builder != NULL);

  ast_t* ast = NULL;
  ast_t* last_child = NULL;

  while(true)
  {
    ast_token_id id = get_token(builder);
    ast_t* child = NULL;
    bool is_type = false;

    if(id == terminator)
    {
      if(ast == NULL)
        build_error(builder, "Syntax error");

      if(ast_id(ast) == TK_MINUS && ast_childcount(ast) == 1)
        ast_setid(ast, TK_UNARY_MINUS);

      return ast;
    }

    if(id == AT_ID)
      id = keyword_replace(builder);

    switch(id)
    {
      case AT_LPAREN:
        child = get_nodes(builder, AT_RPAREN);
        break;

      case AT_LSQUARE:
        child = get_type(builder, ast);
        is_type = true;
        break;

      case AT_ERROR:  // Propogate
        break;

      case AT_STRING:
      case AT_TOKEN:
        child = ast_token(builder->token);
        save_token(builder);
        get_attributes(builder, child);
        break;

      case AT_ID:
        if(strcmp("id", token_string(builder->token)) == 0)
          return get_id(builder, ast);

        build_error(builder, "Unrecognised identifier \"%s\"",
          token_string(builder->token));
        break;

      default:
        build_error(builder, "Syntax error");
        break;
    }

    if(child == NULL)
    {
      // An error occurred and should already have been reported
      ast_free(ast);
      return NULL;
    }

    if(ast == NULL)
    {
      ast = child;
      last_child = NULL;
    }
    else if(is_type)
    {
      ast_settype(ast, child);
    }
    else
    {
      if(last_child == NULL)
        ast_add(ast, child);
      else
        ast_add_sibling(last_child, child);

      last_child = child;
    }
  }
}