为什么野牛inclusion不适用于/扩展到工会%?

kgsdhlau  于 2022-12-03  发布在  其他
关注(0)|答案(2)|浏览(143)

这是我的程序的开始。我一直收到错误boolExpr.y:13:2:错误:未知类型名“bool”bool boolean;但是当我检查野牛生成的文件时,我可以看到stdbool. h被包含在程序执行的开始处。我不明白为什么一个库很重要,但是bool却没有被识别出来。我想我遗漏了一些简单的东西,或者我需要重新安装bison或lex。如果需要的话,我可以包含程序的其余部分。
我试图将其转换为int布尔值;而不是bool布尔值;这就解决了编译问题,但它仍然让我感到困惑。有没有什么方法可以将指向结构体的指针扩展到%union中而不会出现编译错误?我尝试将structName * 布尔值;以替换bool boolean,但它也会作为未定义的wimplicit错误返回。

%{
#include "semantics.h"
#include <stdbool.h>
#include "IOMngr.h"
#include <string.h>
extern int yylex(); /* The next token function. */
extern char *yytext; /* The matched token text. */
extern int yyerror(char *s);
extern SymTab *table;
extern SymEntry *entry; 
%}
%union{
 bool boolean;(this is the line # of error)
 char * string;
}
%type <string> Id
%type <boolean> Expr
%type <boolean> Term
%type <boolean> Factor
%token Ident
%token TRUE
%token FALSE
%token OR
%token AND
%%
Prog : StmtSeq {printSymTab();};
StmtSeq : Stmt StmtSeq { };
StmtSeq : { };
Stmt : Id '=' Expr ';' {storeVar($1, $3);};
Expr : Expr OR Term {$$ = doOR($1, $3);};
Expr : Term {$$ = $1;};
Term : Term AND Factor {$$ = doAND($1, $3);};
Term : Factor {$$ = $1;};
Factor : '!' Factor {$$ = doNOT($2);};
Factor : '(' Expr ')' {$$ = $2;};
Factor : Id {$$ = getVal($1);};
Factor : TRUE {$$ = true;};
Factor : FALSE {$$ = false;};
Id : Ident {$$ = strdup(yytext);};
%%
int yyerror(char *s) {
 WriteIndicator(getCurrentColumnNum());
 WriteMessage("Illegal Character in YACC");
 return 1;
}
cnwbcb6i

cnwbcb6i1#

好吧,愚蠢的错误毕竟-在我的莱克斯文件,我有

#include "h4.tab.h"
#include "SymTab.h"
#include <stdbool.h>

但应该是

#include "SymTab.h"
#include <stdbool.h>
#include "h4.tab.h"

没意识到顺序重要!

2fjabf4q

2fjabf4q2#

当使用%union声明时,野牛创建一个名为YYSTYPEunion类型,它在生成的头文件中声明该类型;该类型用于yylval的声明中,它也在生成的头文件中。将声明放在生成的头文件中意味着除了#include在bison生成的头文件中之外,您不需要做任何事情来使yylval及其类型YYSTYPE在词法分析器中可用。
如果在%union声明中引用的所有类型都是标准C类型,这是很好的。但是,如果你想使用一个需要#include d头文件的类型,或者你自己定义的类型,那就有问题了。假设你把必要的行放在野牛代码序言中(%{...}%),编译解析器不会有问题,但是词法分析器会遇到问题。当您对头文件进行#include时,您将有效地插入“union YYSTYPE”声明,并且除非所有引用的类型都已定义,否则该操作将失败。
当然,您可以通过将所有必需的#include和/或定义从.y文件复制到.l文件来解决这个问题,请确保将union+声明所需的代码放在头文件的#include * 之前 *,并将需要定义YYSTYPE的代码放在#include * 之后 *。但这违背了优秀软件设计的原则;这意味着每次在.y文件中更改#include或声明时,都需要考虑是否需要在.l文件中进行类似的更改以及在何处进行类似的更改。
理想的做法是将所有需要插入的内容都安排到生成的头文件中,然后您可以在词法分析器中只插入#include "h4.tab.h",确信您不需要做任何其他事情来确保所需的#include存在并且顺序正确。
为此,野牛提供了%{...}%指令的更灵活的替代方案:

%code [where] {
// code to insert
}

where有几个可能的值,这些值在野牛文档中有说明。其中两个值用于维护生成的头文件:

  • %code requires { ... }在头文件和源文件中插入代码块,在这两种情况下都在union声明之前。这是您应该用于语义和位置类型依赖项的代码块类型。
  • %code provides { ... }也会将代码块插入到头文件和源文件中,但这次是在union声明之后。如果你有一些引用YYSTYPE的接口,你可以使用这种块类型。

您仍然可以使用%{...}%将代码直接插入到输出源代码中。

* %code { ... }

%{...}%类似,它只将代码插入源文件中。与%{...}%不同,它将代码插入源文件中定义的位置,在YYSTYPE和其他声明之后。这避免了%{...}%块的模糊问题,这些代码有时插入得早,有时插入得晚,因此,如果更改明显不相关的野牛的顺序,可能会突然编译失败指令中。

相关问题