我想完成有关varlist声明的解析,
像varlist:id逗号varlist | id。
目前,我需要设置有关var
的列表。
所以我写这段代码:
varlist: id comma varlist{ createtnode($1.idcontext);}
|id{createtnode($1.idcontext);};
但是我发现
$1.idcontext
不是我想要的idcontext
,应该是该id令牌的idcontext。现在,
$1.idcontext
是这句话'varlist'。没有代码操作,此语法将正常运行。typedef struct{
int* TC;
int* FC;
}boolcode;
typedef struct {
char* idcontext;
int constvalue;
int chain;
boolcode ftentry;
}includes;
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef struct{
int classify;
includes unique;
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
VARList: IDENcode COMMA VARList{
if(YYDEBUG)
{printf("6\n");
printf("%s\n",$1.idcontext);
}
varlistnode* newvar=malloc(sizeof(varlistnode));
newvar->varname=$1.idcontext;
newvar->value=0;
newvar->next=NULL;
mynotes->next=newvar;
mynotes=mynotes->next;
}|IDENcode{
if(YYDEBUG)
{printf("7\n");printf("%s\n",$1.idcontext);}
varlistnode* newvar=malloc(sizeof(varlistnode));
newvar->varname=$1.idcontext;
newvar->value=0;
newvar->next=NULL;
mynotes->next=newvar;
mynotes=mynotes->next;
};
单词等待识别:
a,b,c,d
printf()
函数的结果:7
d:
6
c,d:
6
b,c,d:
6
a,b,c,d:enter code here
最佳答案
该程序中的实际问题在该问题中不可见,因为该错误在您的词法扫描器中。
您没有在问题中包含flex文件,但是可以合理地猜测它包含以下内容:
[[:alpha:]_][[:alnum:]_]* { yylval.unique.idcontext = yytext; /* INCORRECT */
return IDENcode;
}
它应该读
[[:alpha:]_][[:alnum:]_]* { yylval.unique.idcontext = strdup(yytext);
return IDENcode;
}
yytext
指向扫描仪的内部缓冲区,每次调用扫描仪时,其内容都会被修改。您看到的只是这个问题的一个温和版本,因为您的输入非常短;如果输入足够长,以至yylex
需要从输入文件中重新填充缓冲区,那么您将在idcontext
字段中看到完整的垃圾。如果要在以后使用该字符串,则需要对其进行复制(然后,当您不再需要该字符串时,请记住记住该副本,这可能是一个挑战。)另一个可能的问题-老实说,我不知道您是否认为这是一个问题,因为您没有指定从调试跟踪中期望的输出-是您的右递归规则:
varlist: id comma varlist { createtnode($1.idcontext); }
| id { createtnode($1.idcontext); }
最终以相反的顺序在
free()
上调用createtnode
,因为匹配规则后将执行减少野牛的动作。像这样使用right-recursion意味着要执行的第一个id
动作实际上是对应于最后一个varlist
的动作。如果希望动作从左到右执行,则需要使用left-recursion:
varlist: varlist comma id { createtnode($3.idcontext); } /* See below */
| id { createtnode($1.idcontext); }
左递归还有其他优点。例如,它不需要所有
id
(和id
)都堆积在解析器的内部堆栈上,等待最终的缩减操作。同样,您没有显示足够多的代码来查看如何使用这些操作的结果。在我看来,您似乎正在尝试创建变量的全局链接列表,其标头存储在全局变量中。 (
comma
显然指向列表的末尾,因此不能用来恢复列表的开头。)如果是这种情况,那么上面的更改应该可以正常工作。但是,将mynotes
的语义值设置为列表标头会更正常,从而避免使用全局变量。这将导致代码看起来更像这样:varlist: id comma varlist { $$ = append($1, createtnode($3.idcontext)); }
| id { $$ = append(newlist(), createtnode($1.idcontext); }