【问题标题】:bison: empty pseudo variables野牛:空的伪变量
【发布时间】:2017-01-11 15:00:52
【问题描述】:

在 cygwin 环境中使用 flex/bison 而不是 lex/yacc 运行 this howto(第 4.3 节)中的示例 6 时,我得到了意外/丢失的输出。

我从下载部分下载并解压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",$2);
        }
        ;

zonecontent:
        OBRACE zonestatements EBRACE

quotedname:
        QUOTE FILENAME QUOTE
        {
                $$=$2;
        }
        ;

zonestatements:
        |
        zonestatements zonestatement SEMICOLON
        ;

zonestatement:
        statements
        |
        FILETOK quotedname
        {
                printf("A zonefile name '%s' was encountered\n", $2);
        }
        ;

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 ();

【问题讨论】:

    标签: bison flex-lexer


    【解决方案1】:

    “警告”assignment makes integer from pointer without a cast 应始终被视为错误,因为它(几乎)总是如此。

    在这种情况下,错误告诉您的是您正在尝试将指针(strdup 的返回值,即char*)存储为整数 (yylval)。

    当然,yylval 不应该是整数。在 yacc/bison 文件的序言中的 C 代码中,包含

    #define YYSTYPE char *
    

    但是该行并没有出现在 yacc/bison 生成的头文件中。 (如果是这样,头文件也将包含yyerror 的定义,例如,这将导致链接问题,因为可执行文件只能有一个函数的定义。)

    因此,在包含野牛头文件之前,您还必须在 (f)lex 输入文件的序言中包含相同的#define(因为在该文件中使用了YYSTYPE,例如声明yylval )。有点令人惊讶的是,声称是 lex 和 yacc 的 HOW-TO 的东西并没有得到正确的答案。您可能需要考虑提交错误修复。

    【讨论】:

    • 是的,这使它工作!注意! #define YYSTYPE char * 必须放在 (f)lex 文件中的 #include "y.tab.h" 上方才能正常工作。
    • @matthiash:是的,我应该提到这一点。我现在已经添加了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 2018-05-19
    相关资源
    最近更新 更多