Flex 和 Bison $variables 给出意想不到的值
Flex and Bison $variables giving unexpected values
在我的词法分析器文件中,我为标记“name”设置了“yylval.str = yytext”。然后在我的野牛文件中,我尝试读取该 str 值以获取字符串形式的名称。但是,当我读到 $2 时,我最终不仅得到了令牌名称,还得到了该行的其余部分。
例如,一行可以是“MOVE Z TO XY”,其中 Z 和 XY 都是名称。在这种情况下,我希望 $2 的值为“Z”,$4 的值为“XY”。
但实际发生的是 $2 的值为“Z TO XY”,而 $4 的值为“XY”。我想 $4 也有同样的问题,但行尾没有其他内容,所以不会引起任何问题。
为什么 $2 会像这样给出该行的其余部分?如何获取变量名称?
(缩短)词法分析器代码:
"MOVE" {return (MOVE);}
"TO" {return (TO);}
([0-9])+ {yylval.num = atoi(yytext); return (INTEGER);}
[a-z][a-z0-9\-]* {yylval.str = _strlwr(yytext); return (NAME);}
(缩短)解析器代码:
%token MOVE
%token TO
%token <num> INTEGER
%token <str> NAME
%union{
int num;
char *str;
}
move:
MOVE NAME TO NAME PERIOD { printf("<Var1: %s>, <Var2: %s>", , );}
| MOVE INTEGER TO NAME PERIOD { printf("<Val: %d>, <Var: %s>", , ); }
输入:
MOVE Z TO XY-1
MOVE 15 TO XY-1
输出:
<Var1: z TO xy-1>, <Var2: xy-1>
<Val: 15>, <Var: xy-1>
In my lexer file I set "yylval.str = yytext" for the token "name". Then in my bison file I try to read that str value to get the name as a string. However, when I read I end up getting not only the token name, but also the rest of the line.
这一点也不奇怪。 yytext
是指向输入缓冲区的指针(in),从当前匹配项的位置开始。当解析器查看 pointed-to 数据时,它们通常不是字符串,因为在标记字符之后通常没有字符串终止符(但请参见下文)。
此外,当解析器着手查看标记的语义值时,词法分析器可能已将新数据读入输入缓冲区,将原始标记文本从您的下方拉出。
How do I just get the variable name?
要将令牌文本作为您以后可以访问的字符串获取,并确保它不会被您修改,您需要复制它。那可能需要在 dynamically-allocated 内存中。 仅在词法分析器操作中,您可以依靠 Flex 提供的临时字符串终止符,因此您可以使用 strdup()
(如果有)来制作这样的副本。您似乎正在使用 Microsoft 的 C 库,它确实有 strdup
.
然后:
[a-z][a-z0-9\-]* {
char *temp = strdup(yytext);
if (temp == NULL) { /* handle allocation error*/}
else {
yylval.str = _strlwr(temp); return (NAME);
}
}
您将需要确保在不再需要时,在指向它们的指针丢失之前,解析器释放您的标记的动态分配的语义值。
在我的词法分析器文件中,我为标记“name”设置了“yylval.str = yytext”。然后在我的野牛文件中,我尝试读取该 str 值以获取字符串形式的名称。但是,当我读到 $2 时,我最终不仅得到了令牌名称,还得到了该行的其余部分。
例如,一行可以是“MOVE Z TO XY”,其中 Z 和 XY 都是名称。在这种情况下,我希望 $2 的值为“Z”,$4 的值为“XY”。 但实际发生的是 $2 的值为“Z TO XY”,而 $4 的值为“XY”。我想 $4 也有同样的问题,但行尾没有其他内容,所以不会引起任何问题。
为什么 $2 会像这样给出该行的其余部分?如何获取变量名称?
(缩短)词法分析器代码:
"MOVE" {return (MOVE);}
"TO" {return (TO);}
([0-9])+ {yylval.num = atoi(yytext); return (INTEGER);}
[a-z][a-z0-9\-]* {yylval.str = _strlwr(yytext); return (NAME);}
(缩短)解析器代码:
%token MOVE
%token TO
%token <num> INTEGER
%token <str> NAME
%union{
int num;
char *str;
}
move:
MOVE NAME TO NAME PERIOD { printf("<Var1: %s>, <Var2: %s>", , );}
| MOVE INTEGER TO NAME PERIOD { printf("<Val: %d>, <Var: %s>", , ); }
输入:
MOVE Z TO XY-1
MOVE 15 TO XY-1
输出:
<Var1: z TO xy-1>, <Var2: xy-1>
<Val: 15>, <Var: xy-1>
In my lexer file I set "yylval.str = yytext" for the token "name". Then in my bison file I try to read that str value to get the name as a string. However, when I read I end up getting not only the token name, but also the rest of the line.
这一点也不奇怪。 yytext
是指向输入缓冲区的指针(in),从当前匹配项的位置开始。当解析器查看 pointed-to 数据时,它们通常不是字符串,因为在标记字符之后通常没有字符串终止符(但请参见下文)。
此外,当解析器着手查看标记的语义值时,词法分析器可能已将新数据读入输入缓冲区,将原始标记文本从您的下方拉出。
How do I just get the variable name?
要将令牌文本作为您以后可以访问的字符串获取,并确保它不会被您修改,您需要复制它。那可能需要在 dynamically-allocated 内存中。 仅在词法分析器操作中,您可以依靠 Flex 提供的临时字符串终止符,因此您可以使用 strdup()
(如果有)来制作这样的副本。您似乎正在使用 Microsoft 的 C 库,它确实有 strdup
.
然后:
[a-z][a-z0-9\-]* {
char *temp = strdup(yytext);
if (temp == NULL) { /* handle allocation error*/}
else {
yylval.str = _strlwr(temp); return (NAME);
}
}
您将需要确保在不再需要时,在指向它们的指针丢失之前,解析器释放您的标记的动态分配的语义值。