这个问题涉及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),以便他们可以访问symbolList,从而能够正确转换传递给函数的任何变量。
因此,我正在像这样进行递归调用:
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'变量。
麻烦的是,当前,没有注释掉第二个symbolList通过,它覆盖了我的第一个操作数,并且它不再具有对symbolList的访问权!
我希望这有道理....一直让我发疯。
谢谢。
编辑: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);
}
最佳答案
可能与您的问题无关(但可能使问题更容易解决),通常将参数传递给递归函数作为参数而不是将其挂在未发布的数据结构上更有意义:
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数据结构而无需对其进行修改。
关于c - 链表不通过递归调用传播,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13142077/