涉及 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);
}