我想完成有关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
答案 0 :(得分:1)
此程序中的实际问题在该问题中不可见,因为该错误在您的词法扫描程序中。
您没有在问题中包含flex文件,但是可以合理地猜测它包含以下内容:
[[:alpha:]_][[:alnum:]_]* { yylval.unique.idcontext = yytext; /* INCORRECT */
return IDENcode;
}
它应该显示
[[:alpha:]_][[:alnum:]_]* { yylval.unique.idcontext = strdup(yytext);
return IDENcode;
}
yytext
指向扫描仪的内部缓冲区,每次调用扫描仪时,其内容都会被修改。您看到的只是此问题的一个温和版本,因为您的输入非常短;如果输入的时间足够长,yylex
需要从输入文件中重新填充缓冲区,那么您将在idcontext
字段中看到完整的垃圾。如果要在以后使用该字符串,则需要对其进行复制(然后,当您不再需要该字符串时,请记住记住free()
该副本,这可能是一个挑战。)< / p>
另一个可能的问题-老实说,我不知道您是否认为这是一个问题,因为您没有从调试跟踪中指定期望的输出-右递归规则:
varlist: id comma varlist { createtnode($1.idcontext); }
| id { createtnode($1.idcontext); }
最终以相反的顺序在createtnode
上调用id
,因为在符合规则时执行了减少野牛行动。这样使用右递归意味着要执行的第一个varlist
操作实际上是对应于最后一个id
的操作。
如果要使动作从左到右执行,则需要使用左递归:
varlist: varlist comma id { createtnode($3.idcontext); } /* See below */
| id { createtnode($1.idcontext); }
左递归还有其他优点。例如,它不需要所有id
(和comma
)都堆积在解析器的内部堆栈上,等待最后的缩减操作。
同样,您没有足够多的代码来查看如何使用这些操作的结果。在我看来,您正在尝试创建变量的全局链接列表,其标头存储在全局变量中。 (mynotes
显然指向列表的末尾,因此不能用来恢复列表的开头。)如果是这种情况,那么上面的更改应该可以正常工作。但是将varlist
的语义值设为列表标头会更正常,避免使用全局变量。这将导致代码看起来更像这样:
varlist: id comma varlist { $$ = append($1, createtnode($3.idcontext)); }
| id { $$ = append(newlist(), createtnode($1.idcontext); }