3

涉及 yacc、bison 等的这个问题有很多开销,它本质上是构建一个用于计算字符串的关键元素的解析树。但是,所有这些都正常工作,我相当有信心,问题在于一个唠叨的链表。

正如我所提到的,我正在使用各种“计算器”,但这个计算器应该接受已存储在链接列表中的变量。像 (add 1 4) 这样的短语工作得很好,但棘手的部分是如果你尝试类似 ((let (firstvar 2)) (add firstvar 4)) 现在,它应该通过一个符号列表(1在这种情况下)并找到 firstvar 的值(在 add 语句之前使用 let 语句创建、实例化和分配)并将其放入链中。

话虽如此,问题是当我尝试将“symbolList”传递给各种操作数时,它会以奇怪和令人困惑的方式覆盖结构。

首先,来自 .h 的主要联合体:

typedef struct
{
    double value;
} NUMBER_AST_NODE;

typedef struct
{ 
    char *name;
} SYMBOL_AST_NODE;

typedef struct
{
   char *name;
   struct ast_node *op1;
   struct ast_node *op2;
} FUNCTION_AST_NODE;

typedef struct ast_symbol
{
    char *name; //symbol name
    struct ast_node *data;

    struct ast_symbol *next;
    struct ast_symbol *parent;
} AST_SYMBOL;

typedef struct ast_node
{
    AST_NODE_TYPE type;
    union
    {
        NUMBER_AST_NODE number;
        FUNCTION_AST_NODE function;
        SYMBOL_AST_NODE symbol;
    } data;

    AST_SYMBOL *symbolList;    
} AST_NODE; 

好的,现在,假设树已经部分创建,问题是“symbolList”仅附加到树的最高成员......所以我需要将它传递给孩子(即操作数 1 &操作数 2) 以便他们可以访问符号列表,从而能够正确翻译任何传递给其函数的变量。

所以,我正在做一个这样的递归调用:

void translate(AST_NODE *p)
{
  //recursive infix traversal.
  if(p->type == NUM_TYPE){
      printf("%6f",(double) p->data.number.value);
  }
  else if (p->type == SYM_TYPE){
      resolveSymbol(p->symbolList, p->data.symbol.name); //this goes and finds the variable, and it does it correctly IF it has the symbolList!
  }
  else if(p->type == FUNC_TYPE){
          printf("( ");

          p->data.function.op1->symbolList = p->symbolList; //passing the symbolList onward

          translate(p->data.function.op1);
          printf( " %c ",resolveOp(resolvdfunc)); //ignore this, it's just displaying the char like '+' for add

          p->data.function.op2->symbolList = p->symbolList; //passing the symbolList onward
          translate(p->data.function.op2);
          printf(" )");
    }
  }

   if (!p)
      return;
} 

好吧,举个例子。假设我注释掉了第二个操作数的 symbolList 传递。然后,像 ((let (a 2)) (add a 4)) 这样的语句就可以正常工作了。但是,显然,如果我尝试 ((let (a 2)) (add 4 a)) 它将不起作用,因为第二个操作数无法访问“a”变量。

问题是,目前,如果没有注释掉第二个传递的符号列表,它会覆盖我的第一个操作数,并且它无法再访问符号列表了!

我希望这是有道理的……这让我发疯了。

谢谢。

编辑:9:22 - 这是 resolveSymbol 代码(根据要求)......

void resolveSymbol(AST_SYMBOL *p, char *name)
{
    if (p == NULL)
        yyerror("No such symbol exists");
    else if (strcmp(p->name, name) == 0) {
        translate(p->data);
    }
    else
        resolveSymbol(p->next, name);
}
4

1 回答 1

1

可能与您的问题无关(但可能更容易解决),通常将参数作为参数传递给递归函数而不是将它们挂在不相关的数据结构上更有意义:

void translate(AST_NODE *p, AST_SYMBOL *symbols) {
  if(p->type == NUM_TYPE) {
    printf("%6f",(double) p->data.number.value);
  } else if (p->type == SYM_TYPE) {
    resolveSymbol(symbols, p->data.symbol.name);
  } else if(p->type == FUNC_TYPE) {
    printf("( ");
    translate(p->data.function.op1, symbols);
    printf( " %c ", resolveOp(resolvdfunc)); //ignore this, it's just displaying the char like '+' for add
    translate(p->data.function.op2, symbols);
    printf(" )");
  }
} 

这样您就可以完全摆脱 symbolList 字段,并且无需修改即可遍历 AST 数据结构。

于 2012-10-30T17:38:22.573 回答