我想完成有关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); }

08-06 22:06