野牛:空伪变量
bison: empty pseudo variables
当 运行 在 this howto(§4.3)中使用 flex/bison 而不是 lex/yacc 中的示例 6 时,我得到 unexpected/missing 输出,在一个 cygwin 环境。
我从下载部分下载并解压缩 example files。在文件 example6.compile 中,我将 'lex' 替换为 'flex',否则保持原样(命令 yacc 在 cygwin 上执行 exec '/usr/bin/bison' -y "$@"
)。那我运行example6.compile。它 运行 没有错误,但有一些警告(见附录)。
然后我运行 example6,并输入示例文本:
zone "." {
type hint;
file "/etc/bind/db.root";
type hint;
};
预期输出为:
A zonefile name '/etc/bind/db.root' was encountered
Complete zone for '.' found
实际输出为:
A zonefile name '' was encountered
Complete zone for '' found
为什么伪变量的值丢失了?
附录
example6.compile:
flex example6.l
yacc --verbose --debug -d example6.y
cc lex.yy.c y.tab.c -o example6
example6.l:
%{
#include <stdio.h>
#include "y.tab.h"
%}
%%
zone return ZONETOK;
file return FILETOK;
[a-zA-Z][a-zA-Z0-9]* yylval=strdup(yytext); return WORD;
[a-zA-Z0-9\/.-]+ yylval=strdup(yytext); return FILENAME;
\" return QUOTE;
\{ return OBRACE;
\} return EBRACE;
; return SEMICOLON;
\n /* ignore EOL */;
[ \t]+ /* ignore whitespace */;
%%
example6.y:
%{
#include <stdio.h>
#include <string.h>
#define YYSTYPE char *
int yydebug=0;
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
int yywrap()
{
return 1;
}
main()
{
yyparse();
}
%}
%token WORD FILENAME QUOTE OBRACE EBRACE SEMICOLON ZONETOK FILETOK
%%
commands:
|
commands command SEMICOLON
;
command:
zone_set
;
zone_set:
ZONETOK quotedname zonecontent
{
printf("Complete zone for '%s' found\n",);
}
;
zonecontent:
OBRACE zonestatements EBRACE
quotedname:
QUOTE FILENAME QUOTE
{
$$=;
}
;
zonestatements:
|
zonestatements zonestatement SEMICOLON
;
zonestatement:
statements
|
FILETOK quotedname
{
printf("A zonefile name '%s' was encountered\n", );
}
;
block:
OBRACE zonestatements EBRACE SEMICOLON
;
statements:
| statements statement
;
statement: WORD | block | quotedname
编译时的警告:
example6.l: In function ‘yylex’:
example6.l:10:7: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
[a-zA-Z][a-zA-Z0-9]* yylval=strdup(yytext); return WORD;
^
example6.l:11:7: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
[a-zA-Z0-9\/.-]+ yylval=strdup(yytext); return FILENAME;
^
example6.y:19:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main()
^
example6.y: In function ‘main’:
example6.y:21:2: warning: implicit declaration of function ‘yyparse’ [-Wimplicit-function-declaration]
yyparse();
^
y.tab.c: In function ‘yyparse’:
y.tab.c:1164:16: warning: implicit declaration of function ‘yylex’ [-Wimplicit-function-declaration]
yychar = yylex ();
"warning" assignment makes integer from pointer without a cast
应始终被视为错误,因为它(几乎)总是如此。
在这种情况下,错误告诉您的是您正试图将指针(strdup
的 return 值,即 char*
)存储到一个整数中(yylval
).
当然,yylval
不应该是整数。在 yacc/bison 文件序言的 C 代码中,您包含
#define YYSTYPE char *
但是该行并没有出现在 yacc/bison 生成的头文件中。 (如果是这样,头文件也会包含 yyerror
的定义,例如,这会导致链接问题,因为可执行文件只能有一个函数定义。)
因此,在包含 bison 头文件之前,您还必须在 (f)lex 输入文件的序言中包含相同的 #define
(因为该文件中使用了 YYSTYPE
,因为例如声明 yylval
)。有点令人惊讶的是,声称是 lex 和 yacc 的 HOW-TO 的东西并没有得到正确的理解;您可能需要考虑提交错误修正。
当 运行 在 this howto(§4.3)中使用 flex/bison 而不是 lex/yacc 中的示例 6 时,我得到 unexpected/missing 输出,在一个 cygwin 环境。
我从下载部分下载并解压缩 example files。在文件 example6.compile 中,我将 'lex' 替换为 'flex',否则保持原样(命令 yacc 在 cygwin 上执行 exec '/usr/bin/bison' -y "$@"
)。那我运行example6.compile。它 运行 没有错误,但有一些警告(见附录)。
然后我运行 example6,并输入示例文本:
zone "." {
type hint;
file "/etc/bind/db.root";
type hint;
};
预期输出为:
A zonefile name '/etc/bind/db.root' was encountered
Complete zone for '.' found
实际输出为:
A zonefile name '' was encountered
Complete zone for '' found
为什么伪变量的值丢失了?
附录
example6.compile:
flex example6.l
yacc --verbose --debug -d example6.y
cc lex.yy.c y.tab.c -o example6
example6.l:
%{
#include <stdio.h>
#include "y.tab.h"
%}
%%
zone return ZONETOK;
file return FILETOK;
[a-zA-Z][a-zA-Z0-9]* yylval=strdup(yytext); return WORD;
[a-zA-Z0-9\/.-]+ yylval=strdup(yytext); return FILENAME;
\" return QUOTE;
\{ return OBRACE;
\} return EBRACE;
; return SEMICOLON;
\n /* ignore EOL */;
[ \t]+ /* ignore whitespace */;
%%
example6.y:
%{
#include <stdio.h>
#include <string.h>
#define YYSTYPE char *
int yydebug=0;
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
int yywrap()
{
return 1;
}
main()
{
yyparse();
}
%}
%token WORD FILENAME QUOTE OBRACE EBRACE SEMICOLON ZONETOK FILETOK
%%
commands:
|
commands command SEMICOLON
;
command:
zone_set
;
zone_set:
ZONETOK quotedname zonecontent
{
printf("Complete zone for '%s' found\n",);
}
;
zonecontent:
OBRACE zonestatements EBRACE
quotedname:
QUOTE FILENAME QUOTE
{
$$=;
}
;
zonestatements:
|
zonestatements zonestatement SEMICOLON
;
zonestatement:
statements
|
FILETOK quotedname
{
printf("A zonefile name '%s' was encountered\n", );
}
;
block:
OBRACE zonestatements EBRACE SEMICOLON
;
statements:
| statements statement
;
statement: WORD | block | quotedname
编译时的警告:
example6.l: In function ‘yylex’:
example6.l:10:7: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
[a-zA-Z][a-zA-Z0-9]* yylval=strdup(yytext); return WORD;
^
example6.l:11:7: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
[a-zA-Z0-9\/.-]+ yylval=strdup(yytext); return FILENAME;
^
example6.y:19:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main()
^
example6.y: In function ‘main’:
example6.y:21:2: warning: implicit declaration of function ‘yyparse’ [-Wimplicit-function-declaration]
yyparse();
^
y.tab.c: In function ‘yyparse’:
y.tab.c:1164:16: warning: implicit declaration of function ‘yylex’ [-Wimplicit-function-declaration]
yychar = yylex ();
"warning" assignment makes integer from pointer without a cast
应始终被视为错误,因为它(几乎)总是如此。
在这种情况下,错误告诉您的是您正试图将指针(strdup
的 return 值,即 char*
)存储到一个整数中(yylval
).
当然,yylval
不应该是整数。在 yacc/bison 文件序言的 C 代码中,您包含
#define YYSTYPE char *
但是该行并没有出现在 yacc/bison 生成的头文件中。 (如果是这样,头文件也会包含 yyerror
的定义,例如,这会导致链接问题,因为可执行文件只能有一个函数定义。)
因此,在包含 bison 头文件之前,您还必须在 (f)lex 输入文件的序言中包含相同的 #define
(因为该文件中使用了 YYSTYPE
,因为例如声明 yylval
)。有点令人惊讶的是,声称是 lex 和 yacc 的 HOW-TO 的东西并没有得到正确的理解;您可能需要考虑提交错误修正。