在C中表示具有节点类型的不同结构的AST

问题描述 投票:0回答:1

我有很多结构,看起来像:

typedef struct ast_function_node
{        
    int node_type;
    ast_node* arguments;
    symbol* sym;
} ast_function_node;

typedef struct ast_while_node
{
    int node_type;
    ast_node* condition;
    ast_node* while_branch;
} ast_while_node;

typedef struct ast_assignment_node
{
    int node_type;
    symbol* sym;
    ast_node* value;
} ast_assignment_node;

typedef struct ast_number_node
{
    int node_type;
    double value;
} ast_number_node;

typedef struct ast_string_node 
{
    int node_type;
    char* value;
} ast_string_node;

etc...

一个基础结构:

typedef struct // Basic AST node
{
  int node_type;
  struct ast_node* left;
  struct ast_node* right;
} ast_node;

我可以很容易地填充这个AST,但是当涉及到遍历它时,我陷入了类型转换的困境。如果我想访问每个节点,查看其类型然后相应地做一些事情,这样做的最佳方法是什么?只是将它投射到ast_node的基本节点当然不会这样做。

parsing abstract-syntax-tree bison flex-lexer yacc
1个回答
2
投票

我在C中这样做的方法是使用带有struct成员的union

typedef struct ast_function
{        
    ast_node* arguments;
    symbol* sym;
} ast_function;

typedef struct ast_while
{
    ast_node* condition;
    ast_node* while_branch;
} ast_while;

typedef struct ast_assignment
{
    symbol* sym;
    ast_node* value;
} ast_assignment;

/* Etc. */

typedef struct ast_node {
  int node_type;
  /* See anonymous unions in any C reference */
  union {
    ast_function   function_data;
    ast_while      while_data;
    ast_assignment assignment_data;
    /* Etc. */
  };
}

那你根本不需要演员:

switch (node->node_type) {
  case AST_FUNCTION:
    handle_function(&node->function_data); 
    break;
  /* Etc. */
}

如果你使node_type成为enum而不是int,编译器将能够在你的switch声明中错过一个可能性时发出警告。

© www.soinside.com 2019 - 2024. All rights reserved.